Problem 668

Square root smooth numbers ≤ 10^10. non_smooth(N) = sum_{p≤r} p + sum_{p>r} floor(N/p), r=isqrt(N) smooth(N) = N - non_smooth(N) Uses sieve for primes up to r, and quotient grouping for large primes.

Answer2811077773
Output2811077773
StatusPASS
Native helperno
Runtime20 ms
Peak memory2816 KB
Time complexityO(n^2) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)?
Space complexityO(n^2)?
ApproachFlow solutionNot curated
VerdictUnknown

Flow source

# Project Euler 668
# Square root smooth numbers ≤ 10^10.
# non_smooth(N) = sum_{p≤r} p + sum_{p>r} floor(N/p), r=isqrt(N)
# smooth(N) = N - non_smooth(N)
# Uses sieve for primes up to r, and quotient grouping for large primes.

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
}

function isqrt(n: i64) -> i64 {
    if n <= 0 { return 0 }
    let mut x: i64 = n
    let mut y: i64 = (x + 1) / 2
    while y < x { x = y; y = (x + n / x) / 2 }
    return x
}

function main() -> i32 {
    let N: i64 = 10000000000
    let r: i64 = isqrt(N)

    # Sieve primes up to r
    let sieve: ptr<i8> = calloc(r + 1, 1)
    if sieve == null { return 1 }
    sieve[0] = 1
    sieve[1] = 1
    let mut p: i64 = 2
    while p * p <= r {
        if sieve[p] == 0 {
            let mut m: i64 = p * p
            while m <= r { sieve[m] = 1; m = m + p }
        }
        p = p + 1
    }

    # Build pi(x) table for x up to r (prefix sum)
    let pi_table: ptr<i64> = calloc(r + 1, 8)
    if pi_table == null { return 1 }
    let mut cnt: i64 = 0
    let mut i: i64 = 2
    while i <= r {
        if sieve[i] == 0 { cnt = cnt + 1 }
        pi_table[i] = cnt
        i = i + 1
    }

    # sum of primes up to r
    let mut sum_small_primes: i64 = 0
    i = 2
    while i <= r {
        if sieve[i] == 0 { sum_small_primes = sum_small_primes + i }
        i = i + 1
    }

    # For p > r: sum floor(N/p) grouped by quotient q = floor(N/p)
    # q ranges from 1 to N/(r+1)
    let qmax: i64 = N / (r + 1)
    let mut sum_large: i64 = 0
    let mut q: i64 = 1
    while q <= qmax {
        let hi: i64 = N / q
        let lo: i64 = N / (q + 1)
        # Count primes in (lo, hi]
        # pi(hi) - pi(lo)
        let mut pi_hi: i64 = 0
        let mut pi_lo: i64 = 0
        if hi <= r {
            pi_hi = pi_table[hi]
        }
        if lo <= r {
            pi_lo = pi_table[lo]
        }
        # For hi > r, we need pi(hi). But hi = N/q and q >= 1, so hi can be up to N.
        # However, for q=1, hi=N which is huge. We need a different approach.
        # Actually for q=1: primes in (N/2, N], which is all primes > N/2.
        # pi(N) - pi(N/2). We don't have pi for values > r.
        # We need a prime counting function for large values.
        # Let's use a segmented approach or Meissel-Lehmer.
        # Actually, for this problem N=10^10, r=10^5. qmax = N/(r+1) ≈ 10^5.
        # For q=1, hi=N=10^10, lo=N/2=5*10^9. We need pi(10^10) - pi(5*10^9).
        # This requires a proper prime counting function.
        # Let me use a different approach: iterate over primes p > r directly.
        # There are about N/ln(N) - r/ln(r) ≈ 5*10^8 primes up to 10^10.
        # That's too many to enumerate.
        # We need Meissel-Lehmer or a sieve up to N.
        # N = 10^10 is too large for a full sieve.
        # Let's use the Lucy_Hedgehog method for pi(x).
        break
        q = q + 1
    }

    # Actually, let me use a different approach entirely.
    # Use the Lucy_Hedgehog sieve to compute pi(x) for all needed values.
    # This method computes pi(n) in O(n^{2/3}) time and space.
    # For N=10^10, n^{2/3} = 10^{20/3} ≈ 4.6*10^6, which is feasible.

    # Lucy_Hedgehog method:
    # We need pi(v) for v = N/k for k=1..r, and v = 1..r.
    # The method maintains S(v, p) = count of integers 2..v that are not
    # crossed off by primes <= p.

    # Collect all needed values
    let MAXV: i64 = r  # number of distinct values
    # Values: N/1, N/2, ..., N/r, and 1, 2, ..., r
    # Large values (N/k for k=1..r where N/k > r): about r values
    # Small values (1..r): r values

    # Use two arrays: small[v] for v=1..r, large[k] for k=1..r (representing N/k)
    let small_s: ptr<i64> = calloc(r + 1, 8)
    let large_s: ptr<i64> = calloc(r + 1, 8)
    if small_s == null || large_s == null { return 1 }

    # Initialize: S(v) = v - 1 (count of 2..v)
    i = 1
    while i <= r {
        small_s[i] = i - 1
        i = i + 1
    }
    i = 1
    while i <= r {
        large_s[i] = N / i - 1
        i = i + 1
    }

    # Sieve: for each prime p, update S values
    p = 2
    while p * p <= N {
        # If p is prime (small_s[p] > small_s[p-1])
        if p <= r {
            if sieve[p] == 0 {
                let sp: i64 = small_s[p - 1]  # S(p-1, p-1) = pi(p-1)
                # Update large values
                i = 1
                while i <= r {
                    let v: i64 = N / i
                    if v < p * p { break }
                    let d: i64 = v / p
                    let val: i64 = 0
                    if d <= r {
                        val = small_s[d]
                    } else {
                        val = large_s[N / d]
                    }
                    large_s[i] = large_s[i] - (val - sp)
                    i = i + 1
                }
                # Update small values
                let mut v: i64 = r
                while v >= p * p {
                    small_s[v] = small_s[v] - (small_s[v / p] - sp)
                    v = v - 1
                }
            }
        }
        p = p + 1
    }

    # Now pi(N/k) = large_s[k] for k=1..r
    # pi(v) = small_s[v] for v=1..r

    # Compute sum_large = sum_{q=1..qmax} q * (pi(N/q) - pi(N/(q+1)))
    # = sum_{q=1..qmax} q * pi(N/q) - sum_{q=1..qmax} q * pi(N/(q+1))
    # = sum_{q=1..qmax} q * pi(N/q) - sum_{q=2..qmax+1} (q-1) * pi(N/q)
    # = pi(N/1) + sum_{q=2..qmax} pi(N/q) - qmax * pi(N/(qmax+1))
    # But this telescoping isn't right. Let me just compute directly.

    sum_large = 0
    q = 1
    while q <= qmax {
        let hi: i64 = N / q
        let lo: i64 = N / (q + 1)
        let pi_hi: i64 = 0
        let pi_lo: i64 = 0
        if hi <= r {
            pi_hi = small_s[hi]
        } else {
            pi_hi = large_s[N / hi]
        }
        if lo <= r {
            pi_lo = small_s[lo]
        } else {
            if lo > 0 {
                pi_lo = large_s[N / lo]
            }
        }
        sum_large = sum_large + q * (pi_hi - pi_lo)
        q = q + 1
    }

    let non_smooth: i64 = sum_small_primes + sum_large
    let ans: i64 = N - non_smooth
    printf("%lld\n", ans)

    free(large_s)
    free(small_s)
    free(pi_table)
    free(sieve)
    return 0
}

Generated C

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Flow runtime helpers */
typedef struct flow_temp_node { struct flow_temp_node* next; } flow_temp_node;
static flow_temp_node* flow_temp_head = NULL;
static int flow_temp_atexit_set = 0;
__attribute__((unused)) static void flow_temp_free_all(void) {
    while (flow_temp_head) {
        flow_temp_node* n = flow_temp_head;
        flow_temp_head = n->next;
        free(n);
    }
}
__attribute__((unused)) static void* flow_temp_alloc(size_t nbytes) {
    flow_temp_node* node = (flow_temp_node*)malloc(sizeof(flow_temp_node) + nbytes);
    if (!node) return NULL;
    node->next = flow_temp_head;
    flow_temp_head = node;
    if (!flow_temp_atexit_set) {
        flow_temp_atexit_set = 1;
        atexit(flow_temp_free_all);
    }
    return (void*)(node + 1);
}
#ifndef FLOW_DIAG
#define FLOW_DIAG(msg) fprintf(stderr, "%s", (msg))
#endif
#ifndef FLOW_LOG
#define FLOW_LOG(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
#ifndef FLOW_LOG_EMPTY
#define FLOW_LOG_EMPTY(fmt) printf(fmt)
#endif
static char* flow_strcat(const char* a, const char* b) {
    size_t la = strlen(a ? a : ""), lb = strlen(b ? b : "");
    char* r = (char*)flow_temp_alloc(la + lb + 1);
    if (!r) return NULL;
    if (la) memcpy(r, a, la);
    if (lb) memcpy(r + la, b, lb);
    r[la + lb] = '\0';
    return r;
}

#define __flow_in_arr(arr, val) __extension__ ({ \
    int _found = 0; \
    size_t _n = sizeof(arr)/sizeof((arr)[0]); \
    for (size_t _i = 0; _i < _n; _i++) { \
        if ((arr)[_i] == (val)) { _found = 1; break; } \
    } _found; })

/* Unified fault handler (MISRA #279) — override with -DFLOW_FAULT_HANDLER=fn */
#ifndef FLOW_FAULT_HANDLER
__attribute__((unused)) static inline void flow_fault_handler(const char* msg) {
    fprintf(stderr, "flow: %s\n", msg ? msg : "fault");
    abort();
#if defined(__GNUC__) || defined(__clang__)
    __builtin_unreachable();
#endif
}
#else
#define flow_fault_handler FLOW_FAULT_HANDLER
#endif
#define flow_div_by_zero_handler() flow_fault_handler("division by zero")
#define flow_shift_ub_handler() flow_fault_handler("invalid shift (amount out of range or left-shift of negative)")

#ifndef FLOW_CHECKED_DIV
#define FLOW_CHECKED_DIV(L, R) (((R) != 0) ? ((L) / (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_MOD
#define FLOW_CHECKED_MOD(L, R) (((R) != 0) ? ((L) % (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHL
#define FLOW_CHECKED_SHL(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull)) && ((L) >= 0)) ? ((L) << (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHR
#define FLOW_CHECKED_SHR(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull))) ? ((L) >> (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif

#include <math.h>

void* _ui_state = NULL;

static inline float i32_to_f32(int32_t v) { return (float)v; }

/* Host stub for @gpu kernels (device codegen replaces this). */
static inline int32_t gpu_thread_id(void) { return 0; }

int64_t isqrt_i64(int64_t n);
int32_t main(void);



int64_t isqrt_i64(int64_t n) {
    if (n <= 0) {
        return 0;
    }
    int64_t x = n;
    int64_t y = FLOW_CHECKED_DIV(((x + 1)), (2));
    while (y < x) {
        x = y;
        y = FLOW_CHECKED_DIV(((x + FLOW_CHECKED_DIV((n), (x)))), (2));
    }
    return x;
}

int32_t main(void) {
    int64_t N = 10000000000;
    int64_t r = isqrt_i64(N);
    int8_t* sieve = (int8_t*)(calloc((r + 1), 1));
    if (sieve == NULL) {
        return 1;
    }
    sieve[0] = 1;
    sieve[1] = 1;
    int64_t p = 2;
    while ((p * p) <= r) {
        if (sieve[p] == 0) {
            int64_t m = (p * p);
            while (m <= r) {
                sieve[m] = 1;
                m = (m + p);
            }
        }
        p = (p + 1);
    }
    int64_t* pi_table = (int64_t*)(calloc((r + 1), 8));
    if (pi_table == NULL) {
        return 1;
    }
    int64_t cnt = 0;
    int64_t i = 2;
    while (i <= r) {
        if (sieve[i] == 0) {
            cnt = (cnt + 1);
        }
        pi_table[i] = cnt;
        i = (i + 1);
    }
    int64_t sum_small_primes = 0;
    i = 2;
    while (i <= r) {
        if (sieve[i] == 0) {
            sum_small_primes = (sum_small_primes + i);
        }
        i = (i + 1);
    }
    int64_t qmax = FLOW_CHECKED_DIV((N), ((r + 1)));
    int64_t sum_large = 0;
    int64_t q = 1;
    while (q <= qmax) {
        int64_t hi = FLOW_CHECKED_DIV((N), (q));
        int64_t lo = FLOW_CHECKED_DIV((N), ((q + 1)));
        int64_t pi_hi = 0;
        int64_t pi_lo = 0;
        if (hi <= r) {
            pi_hi = pi_table[hi];
        }
        if (lo <= r) {
            pi_lo = pi_table[lo];
        }
        break;
        q = (q + 1);
    }
    int64_t MAXV = r;
    int64_t* small_s = (int64_t*)(calloc((r + 1), 8));
    int64_t* large_s = (int64_t*)(calloc((r + 1), 8));
    if ((small_s == NULL || large_s == NULL)) {
        return 1;
    }
    i = 1;
    while (i <= r) {
        small_s[i] = (i - 1);
        i = (i + 1);
    }
    i = 1;
    while (i <= r) {
        large_s[i] = (FLOW_CHECKED_DIV((N), (i)) - 1);
        i = (i + 1);
    }
    p = 2;
    while ((p * p) <= N) {
        if (p <= r) {
            if (sieve[p] == 0) {
                int64_t sp = small_s[(p - 1)];
                i = 1;
                while (i <= r) {
                    int64_t v = FLOW_CHECKED_DIV((N), (i));
                    if (v < (p * p)) {
                        break;
                    }
                    int64_t d = FLOW_CHECKED_DIV((v), (p));
                    int64_t val = 0;
                    if (d <= r) {
                        val = small_s[d];
                    } else {
                        val = large_s[FLOW_CHECKED_DIV((N), (d))];
                    }
                    large_s[i] = (large_s[i] - (val - sp));
                    i = (i + 1);
                }
                int64_t v = r;
                while (v >= (p * p)) {
                    small_s[v] = (small_s[v] - (small_s[FLOW_CHECKED_DIV((v), (p))] - sp));
                    v = (v - 1);
                }
            }
        }
        p = (p + 1);
    }
    sum_large = 0;
    q = 1;
    while (q <= qmax) {
        int64_t hi = FLOW_CHECKED_DIV((N), (q));
        int64_t lo = FLOW_CHECKED_DIV((N), ((q + 1)));
        int64_t pi_hi = 0;
        int64_t pi_lo = 0;
        if (hi <= r) {
            pi_hi = small_s[hi];
        } else {
            pi_hi = large_s[FLOW_CHECKED_DIV((N), (hi))];
        }
        if (lo <= r) {
            pi_lo = small_s[lo];
        } else {
            if (lo > 0) {
                pi_lo = large_s[FLOW_CHECKED_DIV((N), (lo))];
            }
        }
        sum_large = (sum_large + (q * (pi_hi - pi_lo)));
        q = (q + 1);
    }
    int64_t non_smooth = (sum_small_primes + sum_large);
    int64_t ans = (N - non_smooth);
    printf("%lld\n", ans);
    free(large_s);
    free(small_s);
    free(pi_table);
    free(sieve);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%lld\n\00") {addr_space = 0 : i32} : !llvm.array<6 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  func.func @isqrt(%arg0: i64) -> i64 {
    %0 = arith.constant 0 : i32
    %2 = arith.extsi %0 : i32 to i64
    %1 = arith.cmpi sle, %arg0, %2 : i64
    cf.cond_br %1, ^bb0, ^bb1
    ^bb0:
      %3 = arith.constant 0 : i32
      %4 = arith.extsi %3 : i32 to i64
      func.return %4 : i64
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %5 = llvm.mlir.constant(1 : i64) : i64
    %6 = llvm.alloca %5 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %6 : i64, !llvm.ptr
    %7 = llvm.load %6 : !llvm.ptr -> i64
    %8 = arith.constant 1 : i32
    %10 = arith.extsi %8 : i32 to i64
    %9 = arith.addi %7, %10 : i64
    %11 = arith.constant 2 : i32
    %13 = arith.extsi %11 : i32 to i64
    %12 = arith.divsi %9, %13 : i64
    %14 = llvm.mlir.constant(1 : i64) : i64
    %15 = llvm.alloca %14 x i64 : (i64) -> !llvm.ptr
    llvm.store %12, %15 : i64, !llvm.ptr
    cf.br ^bb3
    ^bb3:
    %16 = llvm.load %15 : !llvm.ptr -> i64
    %17 = llvm.load %6 : !llvm.ptr -> i64
    %18 = arith.cmpi slt, %16, %17 : i64
    cf.cond_br %18, ^bb4, ^bb5
    ^bb4:
      %19 = llvm.load %15 : !llvm.ptr -> i64
      llvm.store %19, %6 : i64, !llvm.ptr
      %20 = llvm.load %6 : !llvm.ptr -> i64
      %21 = llvm.load %6 : !llvm.ptr -> i64
      %22 = arith.divsi %arg0, %21 : i64
      %23 = arith.addi %20, %22 : i64
      %24 = arith.constant 2 : i32
      %26 = arith.extsi %24 : i32 to i64
      %25 = arith.divsi %23, %26 : i64
      llvm.store %25, %15 : i64, !llvm.ptr
      cf.br ^bb3
    ^bb5:
    %27 = llvm.load %6 : !llvm.ptr -> i64
    func.return %27 : i64
  }
  func.func @main() -> i32 {
    %28 = arith.constant 5705032704 : i32
    %29 = arith.extsi %28 : i32 to i64
    %30 = func.call @isqrt(%29) : (i64) -> i64
    %32 = arith.constant 1 : i32
    %34 = arith.extsi %32 : i32 to i64
    %33 = arith.addi %30, %34 : i64
    %35 = arith.constant 1 : i32
    %36 = arith.extsi %35 : i32 to i64
    %31 = func.call @calloc(%33, %36) : (i64, i64) -> !llvm.ptr
    %37 = llvm.mlir.zero : !llvm.ptr
    %38 = llvm.icmp "eq" %31, %37 : !llvm.ptr
    cf.cond_br %38, ^bb6, ^bb7
    ^bb6:
      %39 = arith.constant 1 : i32
      func.return %39 : i32
    ^bb7:
      cf.br ^bb8
    ^bb8:
    %40 = arith.constant 1 : i32
    %41 = arith.constant 0 : i32
    %42 = arith.trunci %40 : i32 to i8
    %43 = arith.extsi %41 : i32 to i64
    %44 = llvm.getelementptr %31[%43] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %42, %44 : i8, !llvm.ptr
    %45 = arith.constant 1 : i32
    %46 = arith.constant 1 : i32
    %47 = arith.trunci %45 : i32 to i8
    %48 = arith.extsi %46 : i32 to i64
    %49 = llvm.getelementptr %31[%48] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %47, %49 : i8, !llvm.ptr
    %50 = arith.constant 2 : i32
    %51 = arith.extsi %50 : i32 to i64
    %52 = llvm.mlir.constant(1 : i64) : i64
    %53 = llvm.alloca %52 x i64 : (i64) -> !llvm.ptr
    llvm.store %51, %53 : i64, !llvm.ptr
    cf.br ^bb9
    ^bb9:
    %54 = llvm.load %53 : !llvm.ptr -> i64
    %55 = llvm.load %53 : !llvm.ptr -> i64
    %56 = arith.muli %54, %55 : i64
    %57 = arith.cmpi sle, %56, %30 : i64
    cf.cond_br %57, ^bb10, ^bb11
    ^bb10:
      %59 = llvm.load %53 : !llvm.ptr -> i64
      %60 = llvm.getelementptr %31[%59] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %58 = llvm.load %60 : !llvm.ptr -> i8
      %61 = arith.constant 0 : i32
      %63 = arith.extsi %58 : i8 to i32
      %62 = arith.cmpi eq, %63, %61 : i32
      cf.cond_br %62, ^bb12, ^bb13
      ^bb12:
        %64 = llvm.load %53 : !llvm.ptr -> i64
        %65 = llvm.load %53 : !llvm.ptr -> i64
        %66 = arith.muli %64, %65 : i64
        %67 = llvm.mlir.constant(1 : i64) : i64
        %68 = llvm.alloca %67 x i64 : (i64) -> !llvm.ptr
        llvm.store %66, %68 : i64, !llvm.ptr
        cf.br ^bb15
        ^bb15:
        %69 = llvm.load %68 : !llvm.ptr -> i64
        %70 = arith.cmpi sle, %69, %30 : i64
        cf.cond_br %70, ^bb16, ^bb17
        ^bb16:
          %71 = arith.constant 1 : i32
          %72 = llvm.load %68 : !llvm.ptr -> i64
          %73 = arith.trunci %71 : i32 to i8
          %74 = llvm.getelementptr %31[%72] : (!llvm.ptr, i64) -> !llvm.ptr, i8
          llvm.store %73, %74 : i8, !llvm.ptr
          %75 = llvm.load %68 : !llvm.ptr -> i64
          %76 = llvm.load %53 : !llvm.ptr -> i64
          %77 = arith.addi %75, %76 : i64
          llvm.store %77, %68 : i64, !llvm.ptr
          cf.br ^bb15
        ^bb17:
        cf.br ^bb14
      ^bb13:
        cf.br ^bb14
      ^bb14:
      %78 = llvm.load %53 : !llvm.ptr -> i64
      %79 = arith.constant 1 : i32
      %81 = arith.extsi %79 : i32 to i64
      %80 = arith.addi %78, %81 : i64
      llvm.store %80, %53 : i64, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    %83 = arith.constant 1 : i32
    %85 = arith.extsi %83 : i32 to i64
    %84 = arith.addi %30, %85 : i64
    %86 = arith.constant 8 : i32
    %87 = arith.extsi %86 : i32 to i64
    %82 = func.call @calloc(%84, %87) : (i64, i64) -> !llvm.ptr
    %88 = llvm.mlir.zero : !llvm.ptr
    %89 = llvm.icmp "eq" %82, %88 : !llvm.ptr
    cf.cond_br %89, ^bb18, ^bb19
    ^bb18:
      %90 = arith.constant 1 : i32
      func.return %90 : i32
    ^bb19:
      cf.br ^bb20
    ^bb20:
    %91 = arith.constant 0 : i32
    %92 = arith.extsi %91 : i32 to i64
    %93 = llvm.mlir.constant(1 : i64) : i64
    %94 = llvm.alloca %93 x i64 : (i64) -> !llvm.ptr
    llvm.store %92, %94 : i64, !llvm.ptr
    %95 = arith.constant 2 : i32
    %96 = arith.extsi %95 : i32 to i64
    %97 = llvm.mlir.constant(1 : i64) : i64
    %98 = llvm.alloca %97 x i64 : (i64) -> !llvm.ptr
    llvm.store %96, %98 : i64, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %99 = llvm.load %98 : !llvm.ptr -> i64
    %100 = arith.cmpi sle, %99, %30 : i64
    cf.cond_br %100, ^bb22, ^bb23
    ^bb22:
      %102 = llvm.load %98 : !llvm.ptr -> i64
      %103 = llvm.getelementptr %31[%102] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %101 = llvm.load %103 : !llvm.ptr -> i8
      %104 = arith.constant 0 : i32
      %106 = arith.extsi %101 : i8 to i32
      %105 = arith.cmpi eq, %106, %104 : i32
      cf.cond_br %105, ^bb24, ^bb25
      ^bb24:
        %107 = llvm.load %94 : !llvm.ptr -> i64
        %108 = arith.constant 1 : i32
        %110 = arith.extsi %108 : i32 to i64
        %109 = arith.addi %107, %110 : i64
        llvm.store %109, %94 : i64, !llvm.ptr
        cf.br ^bb26
      ^bb25:
        cf.br ^bb26
      ^bb26:
      %111 = llvm.load %94 : !llvm.ptr -> i64
      %112 = llvm.load %98 : !llvm.ptr -> i64
      %113 = llvm.getelementptr %82[%112] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %111, %113 : i64, !llvm.ptr
      %114 = llvm.load %98 : !llvm.ptr -> i64
      %115 = arith.constant 1 : i32
      %117 = arith.extsi %115 : i32 to i64
      %116 = arith.addi %114, %117 : i64
      llvm.store %116, %98 : i64, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    %118 = arith.constant 0 : i32
    %119 = arith.extsi %118 : i32 to i64
    %120 = llvm.mlir.constant(1 : i64) : i64
    %121 = llvm.alloca %120 x i64 : (i64) -> !llvm.ptr
    llvm.store %119, %121 : i64, !llvm.ptr
    %122 = arith.constant 2 : i32
    %123 = arith.extsi %122 : i32 to i64
    llvm.store %123, %98 : i64, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %124 = llvm.load %98 : !llvm.ptr -> i64
    %125 = arith.cmpi sle, %124, %30 : i64
    cf.cond_br %125, ^bb28, ^bb29
    ^bb28:
      %127 = llvm.load %98 : !llvm.ptr -> i64
      %128 = llvm.getelementptr %31[%127] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %126 = llvm.load %128 : !llvm.ptr -> i8
      %129 = arith.constant 0 : i32
      %131 = arith.extsi %126 : i8 to i32
      %130 = arith.cmpi eq, %131, %129 : i32
      cf.cond_br %130, ^bb30, ^bb31
      ^bb30:
        %132 = llvm.load %121 : !llvm.ptr -> i64
        %133 = llvm.load %98 : !llvm.ptr -> i64
        %134 = arith.addi %132, %133 : i64
        llvm.store %134, %121 : i64, !llvm.ptr
        cf.br ^bb32
      ^bb31:
        cf.br ^bb32
      ^bb32:
      %135 = llvm.load %98 : !llvm.ptr -> i64
      %136 = arith.constant 1 : i32
      %138 = arith.extsi %136 : i32 to i64
      %137 = arith.addi %135, %138 : i64
      llvm.store %137, %98 : i64, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    %139 = arith.constant 1 : i32
    %141 = arith.extsi %139 : i32 to i64
    %140 = arith.addi %30, %141 : i64
    %142 = arith.divsi %29, %140 : i64
    %143 = arith.constant 0 : i32
    %144 = arith.extsi %143 : i32 to i64
    %145 = llvm.mlir.constant(1 : i64) : i64
    %146 = llvm.alloca %145 x i64 : (i64) -> !llvm.ptr
    llvm.store %144, %146 : i64, !llvm.ptr
    %147 = arith.constant 1 : i32
    %148 = arith.extsi %147 : i32 to i64
    %149 = llvm.mlir.constant(1 : i64) : i64
    %150 = llvm.alloca %149 x i64 : (i64) -> !llvm.ptr
    llvm.store %148, %150 : i64, !llvm.ptr
    cf.br ^bb33
    ^bb33:
    %151 = llvm.load %150 : !llvm.ptr -> i64
    %152 = arith.cmpi sle, %151, %142 : i64
    cf.cond_br %152, ^bb34, ^bb35
    ^bb34:
      %153 = llvm.load %150 : !llvm.ptr -> i64
      %154 = arith.divsi %29, %153 : i64
      %155 = llvm.load %150 : !llvm.ptr -> i64
      %156 = arith.constant 1 : i32
      %158 = arith.extsi %156 : i32 to i64
      %157 = arith.addi %155, %158 : i64
      %159 = arith.divsi %29, %157 : i64
      %160 = arith.constant 0 : i32
      %161 = arith.extsi %160 : i32 to i64
      %162 = llvm.mlir.constant(1 : i64) : i64
      %163 = llvm.alloca %162 x i64 : (i64) -> !llvm.ptr
      llvm.store %161, %163 : i64, !llvm.ptr
      %164 = arith.constant 0 : i32
      %165 = arith.extsi %164 : i32 to i64
      %166 = llvm.mlir.constant(1 : i64) : i64
      %167 = llvm.alloca %166 x i64 : (i64) -> !llvm.ptr
      llvm.store %165, %167 : i64, !llvm.ptr
      %168 = arith.cmpi sle, %154, %30 : i64
      cf.cond_br %168, ^bb36, ^bb37
      ^bb36:
        %170 = llvm.getelementptr %82[%154] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %169 = llvm.load %170 : !llvm.ptr -> i64
        llvm.store %169, %163 : i64, !llvm.ptr
        cf.br ^bb38
      ^bb37:
        cf.br ^bb38
      ^bb38:
      %171 = arith.cmpi sle, %159, %30 : i64
      cf.cond_br %171, ^bb39, ^bb40
      ^bb39:
        %173 = llvm.getelementptr %82[%159] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %172 = llvm.load %173 : !llvm.ptr -> i64
        llvm.store %172, %167 : i64, !llvm.ptr
        cf.br ^bb41
      ^bb40:
        cf.br ^bb41
      ^bb41:
      cf.br ^bb35
    ^bb35:
    %175 = arith.constant 1 : i32
    %177 = arith.extsi %175 : i32 to i64
    %176 = arith.addi %30, %177 : i64
    %178 = arith.constant 8 : i32
    %179 = arith.extsi %178 : i32 to i64
    %174 = func.call @calloc(%176, %179) : (i64, i64) -> !llvm.ptr
    %181 = arith.constant 1 : i32
    %183 = arith.extsi %181 : i32 to i64
    %182 = arith.addi %30, %183 : i64
    %184 = arith.constant 8 : i32
    %185 = arith.extsi %184 : i32 to i64
    %180 = func.call @calloc(%182, %185) : (i64, i64) -> !llvm.ptr
    %186 = llvm.mlir.zero : !llvm.ptr
    %187 = llvm.icmp "eq" %174, %186 : !llvm.ptr
    %188 = scf.if %187 -> (i1) {
      %189 = arith.constant true
      scf.yield %189 : i1
    } else {
      %190 = llvm.mlir.zero : !llvm.ptr
      %191 = llvm.icmp "eq" %180, %190 : !llvm.ptr
      scf.yield %191 : i1
    }
    cf.cond_br %188, ^bb42, ^bb43
    ^bb42:
      %192 = arith.constant 1 : i32
      func.return %192 : i32
    ^bb43:
      cf.br ^bb44
    ^bb44:
    %193 = arith.constant 1 : i32
    %194 = arith.extsi %193 : i32 to i64
    llvm.store %194, %98 : i64, !llvm.ptr
    cf.br ^bb45
    ^bb45:
    %195 = llvm.load %98 : !llvm.ptr -> i64
    %196 = arith.cmpi sle, %195, %30 : i64
    cf.cond_br %196, ^bb46, ^bb47
    ^bb46:
      %197 = llvm.load %98 : !llvm.ptr -> i64
      %198 = arith.constant 1 : i32
      %200 = arith.extsi %198 : i32 to i64
      %199 = arith.subi %197, %200 : i64
      %201 = llvm.load %98 : !llvm.ptr -> i64
      %202 = llvm.getelementptr %174[%201] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %199, %202 : i64, !llvm.ptr
      %203 = llvm.load %98 : !llvm.ptr -> i64
      %204 = arith.constant 1 : i32
      %206 = arith.extsi %204 : i32 to i64
      %205 = arith.addi %203, %206 : i64
      llvm.store %205, %98 : i64, !llvm.ptr
      cf.br ^bb45
    ^bb47:
    %207 = arith.constant 1 : i32
    %208 = arith.extsi %207 : i32 to i64
    llvm.store %208, %98 : i64, !llvm.ptr
    cf.br ^bb48
    ^bb48:
    %209 = llvm.load %98 : !llvm.ptr -> i64
    %210 = arith.cmpi sle, %209, %30 : i64
    cf.cond_br %210, ^bb49, ^bb50
    ^bb49:
      %211 = llvm.load %98 : !llvm.ptr -> i64
      %212 = arith.divsi %29, %211 : i64
      %213 = arith.constant 1 : i32
      %215 = arith.extsi %213 : i32 to i64
      %214 = arith.subi %212, %215 : i64
      %216 = llvm.load %98 : !llvm.ptr -> i64
      %217 = llvm.getelementptr %180[%216] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %214, %217 : i64, !llvm.ptr
      %218 = llvm.load %98 : !llvm.ptr -> i64
      %219 = arith.constant 1 : i32
      %221 = arith.extsi %219 : i32 to i64
      %220 = arith.addi %218, %221 : i64
      llvm.store %220, %98 : i64, !llvm.ptr
      cf.br ^bb48
    ^bb50:
    %222 = arith.constant 2 : i32
    %223 = arith.extsi %222 : i32 to i64
    llvm.store %223, %53 : i64, !llvm.ptr
    cf.br ^bb51
    ^bb51:
    %224 = llvm.load %53 : !llvm.ptr -> i64
    %225 = llvm.load %53 : !llvm.ptr -> i64
    %226 = arith.muli %224, %225 : i64
    %227 = arith.cmpi sle, %226, %29 : i64
    cf.cond_br %227, ^bb52, ^bb53
    ^bb52:
      %228 = llvm.load %53 : !llvm.ptr -> i64
      %229 = arith.cmpi sle, %228, %30 : i64
      cf.cond_br %229, ^bb54, ^bb55
      ^bb54:
        %231 = llvm.load %53 : !llvm.ptr -> i64
        %232 = llvm.getelementptr %31[%231] : (!llvm.ptr, i64) -> !llvm.ptr, i8
        %230 = llvm.load %232 : !llvm.ptr -> i8
        %233 = arith.constant 0 : i32
        %235 = arith.extsi %230 : i8 to i32
        %234 = arith.cmpi eq, %235, %233 : i32
        cf.cond_br %234, ^bb57, ^bb58
        ^bb57:
          %237 = llvm.load %53 : !llvm.ptr -> i64
          %238 = arith.constant 1 : i32
          %240 = arith.extsi %238 : i32 to i64
          %239 = arith.subi %237, %240 : i64
          %241 = llvm.getelementptr %174[%239] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %236 = llvm.load %241 : !llvm.ptr -> i64
          %242 = arith.constant 1 : i32
          %243 = arith.extsi %242 : i32 to i64
          llvm.store %243, %98 : i64, !llvm.ptr
          cf.br ^bb60
          ^bb60:
          %244 = llvm.load %98 : !llvm.ptr -> i64
          %245 = arith.cmpi sle, %244, %30 : i64
          cf.cond_br %245, ^bb61, ^bb62
          ^bb61:
            %246 = llvm.load %98 : !llvm.ptr -> i64
            %247 = arith.divsi %29, %246 : i64
            %248 = llvm.load %53 : !llvm.ptr -> i64
            %249 = llvm.load %53 : !llvm.ptr -> i64
            %250 = arith.muli %248, %249 : i64
            %251 = arith.cmpi slt, %247, %250 : i64
            cf.cond_br %251, ^bb63, ^bb64
            ^bb63:
              cf.br ^bb62
            ^bb64:
              cf.br ^bb65
            ^bb65:
            %252 = llvm.load %53 : !llvm.ptr -> i64
            %253 = arith.divsi %247, %252 : i64
            %254 = arith.constant 0 : i32
            %255 = arith.extsi %254 : i32 to i64
            %256 = arith.cmpi sle, %253, %30 : i64
            %257 = scf.if %256 -> (i64) {
              %259 = llvm.getelementptr %174[%253] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %258 = llvm.load %259 : !llvm.ptr -> i64
              scf.yield %258 : i64
            } else {
              %261 = arith.divsi %29, %253 : i64
              %262 = llvm.getelementptr %180[%261] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %260 = llvm.load %262 : !llvm.ptr -> i64
              scf.yield %260 : i64
            }
            %264 = llvm.load %98 : !llvm.ptr -> i64
            %265 = llvm.getelementptr %180[%264] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %263 = llvm.load %265 : !llvm.ptr -> i64
            %266 = arith.subi %257, %236 : i64
            %267 = arith.subi %263, %266 : i64
            %268 = llvm.load %98 : !llvm.ptr -> i64
            %269 = llvm.getelementptr %180[%268] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %267, %269 : i64, !llvm.ptr
            %270 = llvm.load %98 : !llvm.ptr -> i64
            %271 = arith.constant 1 : i32
            %273 = arith.extsi %271 : i32 to i64
            %272 = arith.addi %270, %273 : i64
            llvm.store %272, %98 : i64, !llvm.ptr
            cf.br ^bb60
          ^bb62:
          %274 = llvm.mlir.constant(1 : i64) : i64
          %275 = llvm.alloca %274 x i64 : (i64) -> !llvm.ptr
          llvm.store %30, %275 : i64, !llvm.ptr
          cf.br ^bb66
          ^bb66:
          %276 = llvm.load %275 : !llvm.ptr -> i64
          %277 = llvm.load %53 : !llvm.ptr -> i64
          %278 = llvm.load %53 : !llvm.ptr -> i64
          %279 = arith.muli %277, %278 : i64
          %280 = arith.cmpi sge, %276, %279 : i64
          cf.cond_br %280, ^bb67, ^bb68
          ^bb67:
            %282 = llvm.load %275 : !llvm.ptr -> i64
            %283 = llvm.getelementptr %174[%282] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %281 = llvm.load %283 : !llvm.ptr -> i64
            %285 = llvm.load %275 : !llvm.ptr -> i64
            %286 = llvm.load %53 : !llvm.ptr -> i64
            %287 = arith.divsi %285, %286 : i64
            %288 = llvm.getelementptr %174[%287] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %284 = llvm.load %288 : !llvm.ptr -> i64
            %289 = arith.subi %284, %236 : i64
            %290 = arith.subi %281, %289 : i64
            %291 = llvm.load %275 : !llvm.ptr -> i64
            %292 = llvm.getelementptr %174[%291] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %290, %292 : i64, !llvm.ptr
            %293 = llvm.load %275 : !llvm.ptr -> i64
            %294 = arith.constant 1 : i32
            %296 = arith.extsi %294 : i32 to i64
            %295 = arith.subi %293, %296 : i64
            llvm.store %295, %275 : i64, !llvm.ptr
            cf.br ^bb66
          ^bb68:
          cf.br ^bb59
        ^bb58:
          cf.br ^bb59
        ^bb59:
        cf.br ^bb56
      ^bb55:
        cf.br ^bb56
      ^bb56:
      %297 = llvm.load %53 : !llvm.ptr -> i64
      %298 = arith.constant 1 : i32
      %300 = arith.extsi %298 : i32 to i64
      %299 = arith.addi %297, %300 : i64
      llvm.store %299, %53 : i64, !llvm.ptr
      cf.br ^bb51
    ^bb53:
    %301 = arith.constant 0 : i32
    %302 = arith.extsi %301 : i32 to i64
    llvm.store %302, %146 : i64, !llvm.ptr
    %303 = arith.constant 1 : i32
    %304 = arith.extsi %303 : i32 to i64
    llvm.store %304, %150 : i64, !llvm.ptr
    cf.br ^bb69
    ^bb69:
    %305 = llvm.load %150 : !llvm.ptr -> i64
    %306 = arith.cmpi sle, %305, %142 : i64
    cf.cond_br %306, ^bb70, ^bb71
    ^bb70:
      %307 = llvm.load %150 : !llvm.ptr -> i64
      %308 = arith.divsi %29, %307 : i64
      %309 = llvm.load %150 : !llvm.ptr -> i64
      %310 = arith.constant 1 : i32
      %312 = arith.extsi %310 : i32 to i64
      %311 = arith.addi %309, %312 : i64
      %313 = arith.divsi %29, %311 : i64
      %314 = arith.constant 0 : i32
      %315 = arith.extsi %314 : i32 to i64
      %316 = arith.constant 0 : i32
      %317 = arith.extsi %316 : i32 to i64
      %318 = arith.cmpi sle, %308, %30 : i64
      %319 = scf.if %318 -> (i64) {
        %321 = llvm.getelementptr %174[%308] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %320 = llvm.load %321 : !llvm.ptr -> i64
        scf.yield %320 : i64
      } else {
        %323 = arith.divsi %29, %308 : i64
        %324 = llvm.getelementptr %180[%323] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %322 = llvm.load %324 : !llvm.ptr -> i64
        scf.yield %322 : i64
      }
      %325 = arith.cmpi sle, %313, %30 : i64
      cf.cond_br %325, ^bb72, ^bb73
      ^bb72:
        %327 = llvm.getelementptr %174[%313] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %326 = llvm.load %327 : !llvm.ptr -> i64
        cf.br ^bb74(%326 : i64)
      ^bb73:
        %328 = arith.constant 0 : i32
        %330 = arith.extsi %328 : i32 to i64
        %329 = arith.cmpi sgt, %313, %330 : i64
        %331 = scf.if %329 -> (i64) {
          %333 = arith.divsi %29, %313 : i64
          %334 = llvm.getelementptr %180[%333] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %332 = llvm.load %334 : !llvm.ptr -> i64
          scf.yield %332 : i64
        } else {
          scf.yield %317 : i64
        }
        cf.br ^bb74(%331 : i64)
      ^bb74(%335: i64):
      %336 = llvm.load %146 : !llvm.ptr -> i64
      %337 = llvm.load %150 : !llvm.ptr -> i64
      %338 = arith.subi %319, %335 : i64
      %339 = arith.muli %337, %338 : i64
      %340 = arith.addi %336, %339 : i64
      llvm.store %340, %146 : i64, !llvm.ptr
      %341 = llvm.load %150 : !llvm.ptr -> i64
      %342 = arith.constant 1 : i32
      %344 = arith.extsi %342 : i32 to i64
      %343 = arith.addi %341, %344 : i64
      llvm.store %343, %150 : i64, !llvm.ptr
      cf.br ^bb69
    ^bb71:
    %345 = llvm.load %121 : !llvm.ptr -> i64
    %346 = llvm.load %146 : !llvm.ptr -> i64
    %347 = arith.addi %345, %346 : i64
    %348 = arith.subi %29, %347 : i64
    %349 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %350 = llvm.call @printf(%349, %348) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    func.call @free(%180) : (!llvm.ptr) -> ()
    func.call @free(%174) : (!llvm.ptr) -> ()
    func.call @free(%82) : (!llvm.ptr) -> ()
    func.call @free(%31) : (!llvm.ptr) -> ()
    %355 = arith.constant 0 : i32
    func.return %355 : i32
  }
}