Problem 319

t(10^10) mod 10^9 via Möbius / Mertens + geometric G.

Answer268457129
Output268457129
StatusPASS
Native helperno
Runtime170 ms
Peak memory64112 KB
Time complexityO(n) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n)O(n log n)
Space complexityO(n^2)O(n)
ApproachFlow solutionModular DP or matrix exponentiation
VerdictOptimal

Flow source

# Project Euler 319
# t(10^10) mod 10^9 via Möbius / Mertens + geometric G.

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

function icbrt(n: i64) -> i64 {
    if n <= 0 { return 0 }
    let mut x: i64 = 1
    while x * x * x <= n { x = x * 2 }
    let mut lo: i64 = 0
    let mut hi: i64 = x
    while lo + 1 < hi {
        let mid: i64 = (lo + hi) / 2
        if mid * mid * mid <= n { lo = mid } else { hi = mid }
    }
    return lo
}

function modpow(base: i64, exp: i64, mod: i64) -> i64 {
    let mut r: i64 = 1
    let mut b: i64 = ((base % mod) + mod) % mod
    let mut e: i64 = exp
    while e > 0 {
        if e % 2 == 1 { r = (r * b) % mod }
        b = (b * b) % mod
        e = e / 2
    }
    return r
}

function slot(n: i64, keys: ptr<i64>, used: ptr<i8>, cap: i64) -> i64 {
    let mut h: i64 = n % cap
    if h < 0 { h = h + cap }
    while used[h] == 1 && keys[h] != n {
        h = h + 1
        if h == cap { h = 0 }
    }
    return h
}

function M(n: i64, pref: ptr<i32>, lim: i64, keys: ptr<i64>, vals: ptr<i64>, used: ptr<i8>, cap: i64) -> i64
function M(n: i64, pref: ptr<i32>, lim: i64, keys: ptr<i64>, vals: ptr<i64>, used: ptr<i8>, cap: i64) -> i64 {
    if n <= 0 { return 0 }
    if n <= lim { return pref[n] as i64 }
    let s: i64 = slot(n, keys, used, cap)
    if used[s] == 1 { return vals[s] }
    let mut res: i64 = 1
    let mut i: i64 = 2
    while i <= n {
        let q: i64 = n / i
        let j: i64 = n / q
        res = res - (j - i + 1) * M(q, pref, lim, keys, vals, used, cap)
        i = j + 1
    }
    used[s] = 1
    keys[s] = n
    vals[s] = res
    return res
}

function G_mod(m: i64, mod: i64) -> i64 {
    if m <= 0 { return 0 }
    let mod2: i64 = 2 * mod
    let num: i64 = (modpow(3, m + 1, mod2) - 3 + mod2) % mod2
    let sum3: i64 = (num / 2) % mod
    let sum2: i64 = (modpow(2, m + 1, mod) - 2 + mod) % mod
    return (sum3 - sum2 - (m % mod) + 2 * mod) % mod
}

function main() -> i32 {
    let N: i64 = 10000000000
    let mod: i64 = 1000000000
    let c: i64 = icbrt(N)
    let lim: i64 = c * c
    let is_comp: ptr<i8> = calloc(lim + 1, 1)
    let mu: ptr<i8> = calloc(lim + 1, 1)
    let primes: ptr<i32> = calloc(lim / 5 + 10, 4)
    mu[1] = 1
    let mut pc: i64 = 0
    let mut i: i64 = 2
    while i <= lim {
        if is_comp[i] == 0 {
            primes[pc] = i as i32
            pc = pc + 1
            mu[i] = -1
        }
        let mut j: i64 = 0
        while j < pc {
            let p: i64 = primes[j] as i64
            let ip: i64 = i * p
            if ip > lim { break }
            is_comp[ip] = 1
            if i % p == 0 {
                mu[ip] = 0
                break
            }
            mu[ip] = (0 - (mu[i] as i64)) as i8
            j = j + 1
        }
        i = i + 1
    }
    let pref: ptr<i32> = calloc(lim + 1, 4)
    let mut s: i64 = 0
    i = 1
    while i <= lim {
        s = s + (mu[i] as i64)
        pref[i] = s as i32
        i = i + 1
    }
    let cap: i64 = 2097152
    let keys: ptr<i64> = calloc(cap, 8)
    let vals: ptr<i64> = calloc(cap, 8)
    let used: ptr<i8> = calloc(cap, 1)

    let mut ans: i64 = 0
    i = 1
    while i <= N {
        let q: i64 = N / i
        let j: i64 = N / q
        let mu_sum: i64 = M(j, pref, lim, keys, vals, used, cap) - M(i - 1, pref, lim, keys, vals, used, cap)
        ans = (ans + (mu_sum % mod + mod) % mod * G_mod(q, mod)) % mod
        i = j + 1
    }
    printf("%lld\n", (ans + 1) % mod)
    free(is_comp); free(mu); free(primes); free(pref); free(keys); free(vals); free(used)
    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 icbrt_i64(int64_t n);
int64_t modpow_i64_i64_i64(int64_t base, int64_t exp, int64_t mod);
int64_t slot_i64_ptr_i64_ptr_i8_i64(int64_t n, int64_t* keys, int8_t* used, int64_t cap);
int64_t M_i64_ptr_i32_i64_ptr_i64_ptr_i64_ptr_i8_i64(int64_t n, int32_t* pref, int64_t lim, int64_t* keys, int64_t* vals, int8_t* used, int64_t cap);
int64_t M_i64_ptr_i32_i64_ptr_i64_ptr_i64_ptr_i8_i64(int64_t n, int32_t* pref, int64_t lim, int64_t* keys, int64_t* vals, int8_t* used, int64_t cap);
int64_t G_mod_i64_i64(int64_t m, int64_t mod);
int32_t main(void);



int64_t icbrt_i64(int64_t n) {
    if (n <= 0) {
        return 0;
    }
    int64_t x = 1;
    while (((x * x) * x) <= n) {
        x = (x * 2);
    }
    int64_t lo = 0;
    int64_t hi = x;
    while ((lo + 1) < hi) {
        int64_t mid = FLOW_CHECKED_DIV(((lo + hi)), (2));
        if (((mid * mid) * mid) <= n) {
            lo = mid;
        } else {
            hi = mid;
        }
    }
    return lo;
}

int64_t modpow_i64_i64_i64(int64_t base, int64_t exp, int64_t mod) {
    int64_t r = 1;
    int64_t b = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD((base), (mod)) + mod)), (mod));
    int64_t e = exp;
    while (e > 0) {
        if (FLOW_CHECKED_MOD((e), (2)) == 1) {
            r = FLOW_CHECKED_MOD(((r * b)), (mod));
        }
        b = FLOW_CHECKED_MOD(((b * b)), (mod));
        e = FLOW_CHECKED_DIV((e), (2));
    }
    return r;
}

int64_t slot_i64_ptr_i64_ptr_i8_i64(int64_t n, int64_t* keys, int8_t* used, int64_t cap) {
    int64_t h = FLOW_CHECKED_MOD((n), (cap));
    if (h < 0) {
        h = (h + cap);
    }
    while ((used[h] == 1 && keys[h] != n)) {
        h = (h + 1);
        if (h == cap) {
            h = 0;
        }
    }
    return h;
}


int64_t M_i64_ptr_i32_i64_ptr_i64_ptr_i64_ptr_i8_i64(int64_t n, int32_t* pref, int64_t lim, int64_t* keys, int64_t* vals, int8_t* used, int64_t cap) {
    if (n <= 0) {
        return 0;
    }
    if (n <= lim) {
        return ((int64_t)(pref[n]));
    }
    int64_t s = slot_i64_ptr_i64_ptr_i8_i64(n, keys, used, cap);
    if (used[s] == 1) {
        return vals[s];
    }
    int64_t res = 1;
    int64_t i = 2;
    while (i <= n) {
        int64_t q = FLOW_CHECKED_DIV((n), (i));
        int64_t j = FLOW_CHECKED_DIV((n), (q));
        res = (res - (((j - i) + 1) * M_i64_ptr_i32_i64_ptr_i64_ptr_i64_ptr_i8_i64(q, pref, lim, keys, vals, used, cap)));
        i = (j + 1);
    }
    used[s] = 1;
    keys[s] = n;
    vals[s] = res;
    return res;
}

int64_t G_mod_i64_i64(int64_t m, int64_t mod) {
    if (m <= 0) {
        return 0;
    }
    int64_t mod2 = (2 * mod);
    int64_t num = FLOW_CHECKED_MOD((((modpow_i64_i64_i64(3, (m + 1), mod2) - 3) + mod2)), (mod2));
    int64_t sum3 = FLOW_CHECKED_MOD((FLOW_CHECKED_DIV((num), (2))), (mod));
    int64_t sum2 = FLOW_CHECKED_MOD((((modpow_i64_i64_i64(2, (m + 1), mod) - 2) + mod)), (mod));
    return FLOW_CHECKED_MOD(((((sum3 - sum2) - FLOW_CHECKED_MOD((m), (mod))) + (2 * mod))), (mod));
}

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