Problem 956

Root-of-unity filter over prime exponents, mod 999999001. Ported from native C to pure Flow. Uses i128 for modular multiplication.

Answer882086212
Output882086212
StatusPASS
Native helperno
Runtime150 ms
Peak memory1088 KB
Time complexityO(n^3) (estimated)
Space complexityO(1) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^3)O(log n)
Space complexityO(1)O(1)
ApproachFlow solutionModular exponentiation
VerdictSuboptimal

Flow source

# Project Euler 956
# Root-of-unity filter over prime exponents, mod 999999001.
# Ported from native C to pure Flow. Uses i128 for modular multiplication.

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

const MOD: i64 = 999999001
const ROOT: i64 = 17
const N: i64 = 1000

function mod_pow(a: i64, e: i64, mod: i64) -> i64 {
    let mut r: i64 = 1 % mod
    let mut aa: i64 = a % mod
    if aa < 0 {
        aa = aa + mod
    }
    let mut ee: i64 = e
    while ee > 0 {
        if (ee & 1) == 1 {
            r = ((r as i128) * (aa as i128) % (mod as i128)) as i64
        }
        aa = ((aa as i128) * (aa as i128) % (mod as i128)) as i64
        ee = ee >> 1
    }
    return r
}

function mod_inv(a: i64, mod: i64) -> i64 {
    return mod_pow(a, mod - 2, mod)
}

function main() -> i32 {
    let N_lim: i64 = N

    # Sieve primes up to N_lim
    let is_prime: ptr<i8> = malloc((N_lim + 1) * 1) as ptr<i8>
    let mut ii: i64 = 0
    while ii <= N_lim {
        is_prime[ii] = 1
        ii = ii + 1
    }
    is_prime[0] = 0
    is_prime[1] = 0

    let primes: ptr<i64> = malloc(256 * 8) as ptr<i64>
    let mut np: i64 = 0
    let mut i: i64 = 2
    while i <= N_lim {
        if is_prime[i] == 1 {
            primes[np] = i
            np = np + 1
            let mut j: i64 = i * i
            while j <= N_lim {
                is_prime[j] = 0
                j = j + i
            }
        }
        i = i + 1
    }

    # Compute exponents for each prime
    let exps: ptr<i64> = malloc(np * 8) as ptr<i64>
    let vp_in_k: ptr<i32> = malloc((N_lim + 1) * 4) as ptr<i32>
    let fact_vp: ptr<i64> = malloc((N_lim + 1) * 8) as ptr<i64>

    let mut pi: i64 = 0
    while pi < np {
        let p: i64 = primes[pi]
        let mut k: i64 = 0
        while k <= N_lim {
            vp_in_k[k] = 0
            k = k + 1
        }
        k = 1
        while k <= N_lim {
            let mut x: i64 = k
            let mut c: i32 = 0
            while x % p == 0 {
                x = x / p
                c = c + 1
            }
            vp_in_k[k] = c
            k = k + 1
        }
        fact_vp[0] = 0
        k = 1
        while k <= N_lim {
            fact_vp[k] = fact_vp[k - 1] + (vp_in_k[k] as i64)
            k = k + 1
        }
        let mut E: i64 = 0
        k = 1
        while k <= N_lim {
            E = E + (N_lim + 1 - k) * fact_vp[k]
            k = k + 1
        }
        exps[pi] = E
        pi = pi + 1
    }

    let m: i64 = N_lim
    let omega: i64 = mod_pow(ROOT, (MOD - 1) / m, MOD)
    let inv_m: i64 = mod_inv(m, MOD)
    let mut ans: i64 = 0
    let mut w: i64 = 1
    let mut t: i64 = 0
    while t < m {
        let mut prod: i64 = 1
        let mut pi2: i64 = 0
        while pi2 < np {
            let p: i64 = primes[pi2]
            let E: i64 = exps[pi2]
            let r: i64 = ((p as i128) * (w as i128) % (MOD as i128)) as i64
            let mut term: i64 = 0
            if r == 1 {
                term = (E + 1) % MOD
            } else {
                let num: i64 = (mod_pow(r, E + 1, MOD) - 1 + MOD) % MOD
                let den: i64 = (r - 1 + MOD) % MOD
                let den_inv: i64 = mod_inv(den, MOD)
                term = ((num as i128) * (den_inv as i128) % (MOD as i128)) as i64
            }
            prod = ((prod as i128) * (term as i128) % (MOD as i128)) as i64
            pi2 = pi2 + 1
        }
        ans = (ans + prod) % MOD
        w = ((w as i128) * (omega as i128) % (MOD as i128)) as i64
        t = t + 1
    }
    let result: i64 = ((ans as i128) * (inv_m as i128) % (MOD as i128)) as i64

    free(is_prime)
    free(primes)
    free(exps)
    free(vp_in_k)
    free(fact_vp)
    printf("%lld\n", result)
    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 mod_pow_i64_i64_i64(int64_t a, int64_t e, int64_t mod);
int64_t mod_inv_i64_i64(int64_t a, int64_t mod);
int32_t main(void);

static const int64_t MOD = 999999001;
static const int64_t ROOT = 17;
static const int64_t N = 1000;




int64_t mod_pow_i64_i64_i64(int64_t a, int64_t e, int64_t mod) {
    int64_t r = FLOW_CHECKED_MOD((1), (mod));
    int64_t aa = FLOW_CHECKED_MOD((a), (mod));
    if (aa < 0) {
        aa = (aa + mod);
    }
    int64_t ee = e;
    while (ee > 0) {
        if ((ee & 1) == 1) {
            r = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(r)) * ((__int128)(aa)))), (((__int128)(mod))))));
        }
        aa = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(aa)) * ((__int128)(aa)))), (((__int128)(mod))))));
        ee = FLOW_CHECKED_SHR((ee), (1));
    }
    return r;
}

int64_t mod_inv_i64_i64(int64_t a, int64_t mod) {
    return mod_pow_i64_i64_i64(a, (mod - 2), mod);
}

int32_t main(void) {
    int64_t N_lim = N;
    int8_t* is_prime = (int8_t*)(((int8_t*)(malloc(((N_lim + 1) * 1)))));
    int64_t ii = 0;
    while (ii <= N_lim) {
        is_prime[ii] = 1;
        ii = (ii + 1);
    }
    is_prime[0] = 0;
    is_prime[1] = 0;
    int64_t* primes = (int64_t*)(((int64_t*)(malloc((256 * 8)))));
    int64_t np = 0;
    int64_t i = 2;
    while (i <= N_lim) {
        if (is_prime[i] == 1) {
            primes[np] = i;
            np = (np + 1);
            int64_t j = (i * i);
            while (j <= N_lim) {
                is_prime[j] = 0;
                j = (j + i);
            }
        }
        i = (i + 1);
    }
    int64_t* exps = (int64_t*)(((int64_t*)(malloc((np * 8)))));
    int32_t* vp_in_k = (int32_t*)(((int32_t*)(malloc(((N_lim + 1) * 4)))));
    int64_t* fact_vp = (int64_t*)(((int64_t*)(malloc(((N_lim + 1) * 8)))));
    int64_t pi = 0;
    while (pi < np) {
        int64_t p = primes[pi];
        int64_t k = 0;
        while (k <= N_lim) {
            vp_in_k[k] = 0;
            k = (k + 1);
        }
        k = 1;
        while (k <= N_lim) {
            int64_t x = k;
            int32_t c = 0;
            while (FLOW_CHECKED_MOD((x), (p)) == 0) {
                x = FLOW_CHECKED_DIV((x), (p));
                c = (c + 1);
            }
            vp_in_k[k] = c;
            k = (k + 1);
        }
        fact_vp[0] = 0;
        k = 1;
        while (k <= N_lim) {
            fact_vp[k] = (fact_vp[(k - 1)] + ((int64_t)(vp_in_k[k])));
            k = (k + 1);
        }
        int64_t E = 0;
        k = 1;
        while (k <= N_lim) {
            E = (E + (((N_lim + 1) - k) * fact_vp[k]));
            k = (k + 1);
        }
        exps[pi] = E;
        pi = (pi + 1);
    }
    int64_t m = N_lim;
    int64_t omega = mod_pow_i64_i64_i64(ROOT, FLOW_CHECKED_DIV(((MOD - 1)), (m)), MOD);
    int64_t inv_m = mod_inv_i64_i64(m, MOD);
    int64_t ans = 0;
    int64_t w = 1;
    int64_t t = 0;
    while (t < m) {
        int64_t prod = 1;
        int64_t pi2 = 0;
        while (pi2 < np) {
            int64_t p = primes[pi2];
            int64_t E = exps[pi2];
            int64_t r = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(p)) * ((__int128)(w)))), (((__int128)(MOD))))));
            int64_t term = 0;
            if (r == 1) {
                term = FLOW_CHECKED_MOD(((E + 1)), (MOD));
            } else {
                int64_t num = FLOW_CHECKED_MOD((((mod_pow_i64_i64_i64(r, (E + 1), MOD) - 1) + MOD)), (MOD));
                int64_t den = FLOW_CHECKED_MOD((((r - 1) + MOD)), (MOD));
                int64_t den_inv = mod_inv_i64_i64(den, MOD);
                term = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(num)) * ((__int128)(den_inv)))), (((__int128)(MOD))))));
            }
            prod = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(prod)) * ((__int128)(term)))), (((__int128)(MOD))))));
            pi2 = (pi2 + 1);
        }
        ans = FLOW_CHECKED_MOD(((ans + prod)), (MOD));
        w = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(w)) * ((__int128)(omega)))), (((__int128)(MOD))))));
        t = (t + 1);
    }
    int64_t result = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(ans)) * ((__int128)(inv_m)))), (((__int128)(MOD))))));
    free(is_prime);
    free(primes);
    free(exps);
    free(vp_in_k);
    free(fact_vp);
    printf("%lld\n", result);
    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 private @malloc(i64) -> !llvm.ptr
  // Constant: MOD
  llvm.mlir.global internal constant @MOD(999999001 : i64) : i64
  // Constant: ROOT
  llvm.mlir.global internal constant @ROOT(17 : i64) : i64
  // Constant: N
  llvm.mlir.global internal constant @N(1000 : i64) : i64
  func.func @mod_pow(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %0 = arith.constant 1 : i32
    %2 = arith.extsi %0 : i32 to i64
    %1 = arith.remsi %2, %arg2 : i64
    %3 = llvm.mlir.constant(1 : i64) : i64
    %4 = llvm.alloca %3 x i64 : (i64) -> !llvm.ptr
    llvm.store %1, %4 : i64, !llvm.ptr
    %5 = arith.remsi %arg0, %arg2 : i64
    %6 = llvm.mlir.constant(1 : i64) : i64
    %7 = llvm.alloca %6 x i64 : (i64) -> !llvm.ptr
    llvm.store %5, %7 : i64, !llvm.ptr
    %8 = llvm.load %7 : !llvm.ptr -> i64
    %9 = arith.constant 0 : i32
    %11 = arith.extsi %9 : i32 to i64
    %10 = arith.cmpi slt, %8, %11 : i64
    cf.cond_br %10, ^bb0, ^bb1
    ^bb0:
      %12 = llvm.load %7 : !llvm.ptr -> i64
      %13 = arith.addi %12, %arg2 : i64
      llvm.store %13, %7 : i64, !llvm.ptr
      cf.br ^bb2
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %14 = llvm.mlir.constant(1 : i64) : i64
    %15 = llvm.alloca %14 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %15 : i64, !llvm.ptr
    cf.br ^bb3
    ^bb3:
    %16 = llvm.load %15 : !llvm.ptr -> i64
    %17 = arith.constant 0 : i32
    %19 = arith.extsi %17 : i32 to i64
    %18 = arith.cmpi sgt, %16, %19 : i64
    cf.cond_br %18, ^bb4, ^bb5
    ^bb4:
      %20 = llvm.load %15 : !llvm.ptr -> i64
      %21 = arith.constant 1 : i32
      %23 = arith.extsi %21 : i32 to i64
      %22 = arith.andi %20, %23 : i64
      %24 = arith.constant 1 : i32
      %26 = arith.extsi %24 : i32 to i64
      %25 = arith.cmpi eq, %22, %26 : i64
      cf.cond_br %25, ^bb6, ^bb7
      ^bb6:
        %27 = llvm.load %4 : !llvm.ptr -> i64
        %28 = arith.extsi %27 : i64 to i128
        %29 = llvm.load %7 : !llvm.ptr -> i64
        %30 = arith.extsi %29 : i64 to i128
        %32 = arith.trunci %28 : i128 to i64
        %33 = arith.trunci %30 : i128 to i64
        %31 = arith.muli %32, %33 : i64
        %34 = arith.extsi %arg2 : i64 to i128
        %36 = arith.trunci %34 : i128 to i64
        %35 = arith.remsi %31, %36 : i64
        llvm.store %35, %4 : i64, !llvm.ptr
        cf.br ^bb8
      ^bb7:
        cf.br ^bb8
      ^bb8:
      %37 = llvm.load %7 : !llvm.ptr -> i64
      %38 = arith.extsi %37 : i64 to i128
      %39 = llvm.load %7 : !llvm.ptr -> i64
      %40 = arith.extsi %39 : i64 to i128
      %42 = arith.trunci %38 : i128 to i64
      %43 = arith.trunci %40 : i128 to i64
      %41 = arith.muli %42, %43 : i64
      %44 = arith.extsi %arg2 : i64 to i128
      %46 = arith.trunci %44 : i128 to i64
      %45 = arith.remsi %41, %46 : i64
      llvm.store %45, %7 : i64, !llvm.ptr
      %47 = llvm.load %15 : !llvm.ptr -> i64
      %48 = arith.constant 1 : i32
      %50 = arith.extsi %48 : i32 to i64
      %49 = arith.shrsi %47, %50 : i64
      llvm.store %49, %15 : i64, !llvm.ptr
      cf.br ^bb3
    ^bb5:
    %51 = llvm.load %4 : !llvm.ptr -> i64
    func.return %51 : i64
  }
  func.func @mod_inv(%arg0: i64, %arg1: i64) -> i64 {
    %53 = arith.constant 2 : i32
    %55 = arith.extsi %53 : i32 to i64
    %54 = arith.subi %arg1, %55 : i64
    %52 = func.call @mod_pow(%arg0, %54, %arg1) : (i64, i64, i64) -> i64
    func.return %52 : i64
  }
  func.func @main() -> i32 {
    %56 = llvm.mlir.addressof @N : !llvm.ptr
    %57 = llvm.load %56 : !llvm.ptr -> i64
    %59 = arith.constant 1 : i32
    %61 = arith.extsi %59 : i32 to i64
    %60 = arith.addi %57, %61 : i64
    %62 = arith.constant 1 : i32
    %64 = arith.extsi %62 : i32 to i64
    %63 = arith.muli %60, %64 : i64
    %58 = func.call @malloc(%63) : (i64) -> !llvm.ptr
    %65 = arith.constant 0 : i32
    %66 = arith.extsi %65 : i32 to 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 ^bb9
    ^bb9:
    %69 = llvm.load %68 : !llvm.ptr -> i64
    %70 = arith.cmpi sle, %69, %57 : i64
    cf.cond_br %70, ^bb10, ^bb11
    ^bb10:
      %71 = arith.constant 1 : i32
      %72 = llvm.load %68 : !llvm.ptr -> i64
      %73 = arith.trunci %71 : i32 to i8
      %74 = llvm.getelementptr %58[%72] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      llvm.store %73, %74 : i8, !llvm.ptr
      %75 = llvm.load %68 : !llvm.ptr -> i64
      %76 = arith.constant 1 : i32
      %78 = arith.extsi %76 : i32 to i64
      %77 = arith.addi %75, %78 : i64
      llvm.store %77, %68 : i64, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    %79 = arith.constant 0 : i32
    %80 = arith.constant 0 : i32
    %81 = arith.trunci %79 : i32 to i8
    %82 = arith.extsi %80 : i32 to i64
    %83 = llvm.getelementptr %58[%82] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %81, %83 : i8, !llvm.ptr
    %84 = arith.constant 0 : i32
    %85 = arith.constant 1 : i32
    %86 = arith.trunci %84 : i32 to i8
    %87 = arith.extsi %85 : i32 to i64
    %88 = llvm.getelementptr %58[%87] : (!llvm.ptr, i64) -> !llvm.ptr, i8
    llvm.store %86, %88 : i8, !llvm.ptr
    %90 = arith.constant 256 : i32
    %91 = arith.constant 8 : i32
    %92 = arith.muli %90, %91 : i32
    %93 = arith.extsi %92 : i32 to i64
    %89 = func.call @malloc(%93) : (i64) -> !llvm.ptr
    %94 = arith.constant 0 : i32
    %95 = arith.extsi %94 : i32 to i64
    %96 = llvm.mlir.constant(1 : i64) : i64
    %97 = llvm.alloca %96 x i64 : (i64) -> !llvm.ptr
    llvm.store %95, %97 : i64, !llvm.ptr
    %98 = arith.constant 2 : i32
    %99 = arith.extsi %98 : i32 to i64
    %100 = llvm.mlir.constant(1 : i64) : i64
    %101 = llvm.alloca %100 x i64 : (i64) -> !llvm.ptr
    llvm.store %99, %101 : i64, !llvm.ptr
    cf.br ^bb12
    ^bb12:
    %102 = llvm.load %101 : !llvm.ptr -> i64
    %103 = arith.cmpi sle, %102, %57 : i64
    cf.cond_br %103, ^bb13, ^bb14
    ^bb13:
      %105 = llvm.load %101 : !llvm.ptr -> i64
      %106 = llvm.getelementptr %58[%105] : (!llvm.ptr, i64) -> !llvm.ptr, i8
      %104 = llvm.load %106 : !llvm.ptr -> i8
      %107 = arith.constant 1 : i32
      %109 = arith.extsi %104 : i8 to i32
      %108 = arith.cmpi eq, %109, %107 : i32
      cf.cond_br %108, ^bb15, ^bb16
      ^bb15:
        %110 = llvm.load %101 : !llvm.ptr -> i64
        %111 = llvm.load %97 : !llvm.ptr -> i64
        %112 = llvm.getelementptr %89[%111] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %110, %112 : i64, !llvm.ptr
        %113 = llvm.load %97 : !llvm.ptr -> i64
        %114 = arith.constant 1 : i32
        %116 = arith.extsi %114 : i32 to i64
        %115 = arith.addi %113, %116 : i64
        llvm.store %115, %97 : i64, !llvm.ptr
        %117 = llvm.load %101 : !llvm.ptr -> i64
        %118 = llvm.load %101 : !llvm.ptr -> i64
        %119 = arith.muli %117, %118 : i64
        %120 = llvm.mlir.constant(1 : i64) : i64
        %121 = llvm.alloca %120 x i64 : (i64) -> !llvm.ptr
        llvm.store %119, %121 : i64, !llvm.ptr
        cf.br ^bb18
        ^bb18:
        %122 = llvm.load %121 : !llvm.ptr -> i64
        %123 = arith.cmpi sle, %122, %57 : i64
        cf.cond_br %123, ^bb19, ^bb20
        ^bb19:
          %124 = arith.constant 0 : i32
          %125 = llvm.load %121 : !llvm.ptr -> i64
          %126 = arith.trunci %124 : i32 to i8
          %127 = llvm.getelementptr %58[%125] : (!llvm.ptr, i64) -> !llvm.ptr, i8
          llvm.store %126, %127 : i8, !llvm.ptr
          %128 = llvm.load %121 : !llvm.ptr -> i64
          %129 = llvm.load %101 : !llvm.ptr -> i64
          %130 = arith.addi %128, %129 : i64
          llvm.store %130, %121 : i64, !llvm.ptr
          cf.br ^bb18
        ^bb20:
        cf.br ^bb17
      ^bb16:
        cf.br ^bb17
      ^bb17:
      %131 = llvm.load %101 : !llvm.ptr -> i64
      %132 = arith.constant 1 : i32
      %134 = arith.extsi %132 : i32 to i64
      %133 = arith.addi %131, %134 : i64
      llvm.store %133, %101 : i64, !llvm.ptr
      cf.br ^bb12
    ^bb14:
    %136 = llvm.load %97 : !llvm.ptr -> i64
    %137 = arith.constant 8 : i32
    %139 = arith.extsi %137 : i32 to i64
    %138 = arith.muli %136, %139 : i64
    %135 = func.call @malloc(%138) : (i64) -> !llvm.ptr
    %141 = arith.constant 1 : i32
    %143 = arith.extsi %141 : i32 to i64
    %142 = arith.addi %57, %143 : i64
    %144 = arith.constant 4 : i32
    %146 = arith.extsi %144 : i32 to i64
    %145 = arith.muli %142, %146 : i64
    %140 = func.call @malloc(%145) : (i64) -> !llvm.ptr
    %148 = arith.constant 1 : i32
    %150 = arith.extsi %148 : i32 to i64
    %149 = arith.addi %57, %150 : i64
    %151 = arith.constant 8 : i32
    %153 = arith.extsi %151 : i32 to i64
    %152 = arith.muli %149, %153 : i64
    %147 = func.call @malloc(%152) : (i64) -> !llvm.ptr
    %154 = arith.constant 0 : i32
    %155 = arith.extsi %154 : i32 to i64
    %156 = llvm.mlir.constant(1 : i64) : i64
    %157 = llvm.alloca %156 x i64 : (i64) -> !llvm.ptr
    llvm.store %155, %157 : i64, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %158 = llvm.load %157 : !llvm.ptr -> i64
    %159 = llvm.load %97 : !llvm.ptr -> i64
    %160 = arith.cmpi slt, %158, %159 : i64
    cf.cond_br %160, ^bb22, ^bb23
    ^bb22:
      %162 = llvm.load %157 : !llvm.ptr -> i64
      %163 = llvm.getelementptr %89[%162] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %161 = llvm.load %163 : !llvm.ptr -> i64
      %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
      cf.br ^bb24
      ^bb24:
      %168 = llvm.load %167 : !llvm.ptr -> i64
      %169 = arith.cmpi sle, %168, %57 : i64
      cf.cond_br %169, ^bb25, ^bb26
      ^bb25:
        %170 = arith.constant 0 : i32
        %171 = llvm.load %167 : !llvm.ptr -> i64
        %172 = llvm.getelementptr %140[%171] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %170, %172 : i32, !llvm.ptr
        %173 = llvm.load %167 : !llvm.ptr -> i64
        %174 = arith.constant 1 : i32
        %176 = arith.extsi %174 : i32 to i64
        %175 = arith.addi %173, %176 : i64
        llvm.store %175, %167 : i64, !llvm.ptr
        cf.br ^bb24
      ^bb26:
      %177 = arith.constant 1 : i32
      %178 = arith.extsi %177 : i32 to i64
      llvm.store %178, %167 : i64, !llvm.ptr
      cf.br ^bb27
      ^bb27:
      %179 = llvm.load %167 : !llvm.ptr -> i64
      %180 = arith.cmpi sle, %179, %57 : i64
      cf.cond_br %180, ^bb28, ^bb29
      ^bb28:
        %181 = llvm.load %167 : !llvm.ptr -> i64
        %182 = llvm.mlir.constant(1 : i64) : i64
        %183 = llvm.alloca %182 x i64 : (i64) -> !llvm.ptr
        llvm.store %181, %183 : i64, !llvm.ptr
        %184 = arith.constant 0 : i32
        %185 = llvm.mlir.constant(1 : i64) : i64
        %186 = llvm.alloca %185 x i32 : (i64) -> !llvm.ptr
        llvm.store %184, %186 : i32, !llvm.ptr
        cf.br ^bb30
        ^bb30:
        %187 = llvm.load %183 : !llvm.ptr -> i64
        %188 = arith.remsi %187, %161 : i64
        %189 = arith.constant 0 : i32
        %191 = arith.extsi %189 : i32 to i64
        %190 = arith.cmpi eq, %188, %191 : i64
        cf.cond_br %190, ^bb31, ^bb32
        ^bb31:
          %192 = llvm.load %183 : !llvm.ptr -> i64
          %193 = arith.divsi %192, %161 : i64
          llvm.store %193, %183 : i64, !llvm.ptr
          %194 = llvm.load %186 : !llvm.ptr -> i32
          %195 = arith.constant 1 : i32
          %196 = arith.addi %194, %195 : i32
          llvm.store %196, %186 : i32, !llvm.ptr
          cf.br ^bb30
        ^bb32:
        %197 = llvm.load %186 : !llvm.ptr -> i32
        %198 = llvm.load %167 : !llvm.ptr -> i64
        %199 = llvm.getelementptr %140[%198] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %197, %199 : i32, !llvm.ptr
        %200 = llvm.load %167 : !llvm.ptr -> i64
        %201 = arith.constant 1 : i32
        %203 = arith.extsi %201 : i32 to i64
        %202 = arith.addi %200, %203 : i64
        llvm.store %202, %167 : i64, !llvm.ptr
        cf.br ^bb27
      ^bb29:
      %204 = arith.constant 0 : i32
      %205 = arith.constant 0 : i32
      %206 = arith.extsi %204 : i32 to i64
      %207 = arith.extsi %205 : i32 to i64
      %208 = llvm.getelementptr %147[%207] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %206, %208 : i64, !llvm.ptr
      %209 = arith.constant 1 : i32
      %210 = arith.extsi %209 : i32 to i64
      llvm.store %210, %167 : i64, !llvm.ptr
      cf.br ^bb33
      ^bb33:
      %211 = llvm.load %167 : !llvm.ptr -> i64
      %212 = arith.cmpi sle, %211, %57 : i64
      cf.cond_br %212, ^bb34, ^bb35
      ^bb34:
        %214 = llvm.load %167 : !llvm.ptr -> i64
        %215 = arith.constant 1 : i32
        %217 = arith.extsi %215 : i32 to i64
        %216 = arith.subi %214, %217 : i64
        %218 = llvm.getelementptr %147[%216] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %213 = llvm.load %218 : !llvm.ptr -> i64
        %220 = llvm.load %167 : !llvm.ptr -> i64
        %221 = llvm.getelementptr %140[%220] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %219 = llvm.load %221 : !llvm.ptr -> i32
        %222 = arith.extsi %219 : i32 to i64
        %223 = arith.addi %213, %222 : i64
        %224 = llvm.load %167 : !llvm.ptr -> i64
        %225 = llvm.getelementptr %147[%224] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %223, %225 : i64, !llvm.ptr
        %226 = llvm.load %167 : !llvm.ptr -> i64
        %227 = arith.constant 1 : i32
        %229 = arith.extsi %227 : i32 to i64
        %228 = arith.addi %226, %229 : i64
        llvm.store %228, %167 : i64, !llvm.ptr
        cf.br ^bb33
      ^bb35:
      %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 1 : i32
      %235 = arith.extsi %234 : i32 to i64
      llvm.store %235, %167 : i64, !llvm.ptr
      cf.br ^bb36
      ^bb36:
      %236 = llvm.load %167 : !llvm.ptr -> i64
      %237 = arith.cmpi sle, %236, %57 : i64
      cf.cond_br %237, ^bb37, ^bb38
      ^bb37:
        %238 = llvm.load %233 : !llvm.ptr -> i64
        %239 = arith.constant 1 : i32
        %241 = arith.extsi %239 : i32 to i64
        %240 = arith.addi %57, %241 : i64
        %242 = llvm.load %167 : !llvm.ptr -> i64
        %243 = arith.subi %240, %242 : i64
        %245 = llvm.load %167 : !llvm.ptr -> i64
        %246 = llvm.getelementptr %147[%245] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %244 = llvm.load %246 : !llvm.ptr -> i64
        %247 = arith.muli %243, %244 : i64
        %248 = arith.addi %238, %247 : i64
        llvm.store %248, %233 : i64, !llvm.ptr
        %249 = llvm.load %167 : !llvm.ptr -> i64
        %250 = arith.constant 1 : i32
        %252 = arith.extsi %250 : i32 to i64
        %251 = arith.addi %249, %252 : i64
        llvm.store %251, %167 : i64, !llvm.ptr
        cf.br ^bb36
      ^bb38:
      %253 = llvm.load %233 : !llvm.ptr -> i64
      %254 = llvm.load %157 : !llvm.ptr -> i64
      %255 = llvm.getelementptr %135[%254] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %253, %255 : i64, !llvm.ptr
      %256 = llvm.load %157 : !llvm.ptr -> i64
      %257 = arith.constant 1 : i32
      %259 = arith.extsi %257 : i32 to i64
      %258 = arith.addi %256, %259 : i64
      llvm.store %258, %157 : i64, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    %261 = llvm.mlir.addressof @ROOT : !llvm.ptr
    %262 = llvm.load %261 : !llvm.ptr -> i64
    %263 = llvm.mlir.addressof @MOD : !llvm.ptr
    %264 = llvm.load %263 : !llvm.ptr -> i64
    %265 = arith.constant 1 : i32
    %267 = arith.extsi %265 : i32 to i64
    %266 = arith.subi %264, %267 : i64
    %268 = arith.divsi %266, %57 : i64
    %269 = llvm.mlir.addressof @MOD : !llvm.ptr
    %270 = llvm.load %269 : !llvm.ptr -> i64
    %260 = func.call @mod_pow(%262, %268, %270) : (i64, i64, i64) -> i64
    %272 = llvm.mlir.addressof @MOD : !llvm.ptr
    %273 = llvm.load %272 : !llvm.ptr -> i64
    %271 = func.call @mod_inv(%57, %273) : (i64, i64) -> i64
    %274 = arith.constant 0 : i32
    %275 = arith.extsi %274 : i32 to i64
    %276 = llvm.mlir.constant(1 : i64) : i64
    %277 = llvm.alloca %276 x i64 : (i64) -> !llvm.ptr
    llvm.store %275, %277 : i64, !llvm.ptr
    %278 = arith.constant 1 : i32
    %279 = arith.extsi %278 : i32 to i64
    %280 = llvm.mlir.constant(1 : i64) : i64
    %281 = llvm.alloca %280 x i64 : (i64) -> !llvm.ptr
    llvm.store %279, %281 : i64, !llvm.ptr
    %282 = arith.constant 0 : i32
    %283 = arith.extsi %282 : i32 to i64
    %284 = llvm.mlir.constant(1 : i64) : i64
    %285 = llvm.alloca %284 x i64 : (i64) -> !llvm.ptr
    llvm.store %283, %285 : i64, !llvm.ptr
    cf.br ^bb39
    ^bb39:
    %286 = llvm.load %285 : !llvm.ptr -> i64
    %287 = arith.cmpi slt, %286, %57 : i64
    cf.cond_br %287, ^bb40, ^bb41
    ^bb40:
      %288 = arith.constant 1 : i32
      %289 = arith.extsi %288 : i32 to i64
      %290 = llvm.mlir.constant(1 : i64) : i64
      %291 = llvm.alloca %290 x i64 : (i64) -> !llvm.ptr
      llvm.store %289, %291 : i64, !llvm.ptr
      %292 = arith.constant 0 : i32
      %293 = arith.extsi %292 : i32 to i64
      %294 = llvm.mlir.constant(1 : i64) : i64
      %295 = llvm.alloca %294 x i64 : (i64) -> !llvm.ptr
      llvm.store %293, %295 : i64, !llvm.ptr
      cf.br ^bb42
      ^bb42:
      %296 = llvm.load %295 : !llvm.ptr -> i64
      %297 = llvm.load %97 : !llvm.ptr -> i64
      %298 = arith.cmpi slt, %296, %297 : i64
      cf.cond_br %298, ^bb43, ^bb44
      ^bb43:
        %300 = llvm.load %295 : !llvm.ptr -> i64
        %301 = llvm.getelementptr %89[%300] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %299 = llvm.load %301 : !llvm.ptr -> i64
        %303 = llvm.load %295 : !llvm.ptr -> i64
        %304 = llvm.getelementptr %135[%303] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %302 = llvm.load %304 : !llvm.ptr -> i64
        %305 = arith.extsi %299 : i64 to i128
        %306 = llvm.load %281 : !llvm.ptr -> i64
        %307 = arith.extsi %306 : i64 to i128
        %309 = arith.trunci %305 : i128 to i64
        %310 = arith.trunci %307 : i128 to i64
        %308 = arith.muli %309, %310 : i64
        %311 = llvm.mlir.addressof @MOD : !llvm.ptr
        %312 = llvm.load %311 : !llvm.ptr -> i64
        %313 = arith.extsi %312 : i64 to i128
        %315 = arith.trunci %313 : i128 to i64
        %314 = arith.remsi %308, %315 : i64
        %316 = arith.constant 0 : i32
        %317 = arith.extsi %316 : i32 to i64
        %318 = llvm.mlir.constant(1 : i64) : i64
        %319 = llvm.alloca %318 x i64 : (i64) -> !llvm.ptr
        llvm.store %317, %319 : i64, !llvm.ptr
        %320 = arith.constant 1 : i32
        %322 = arith.extsi %320 : i32 to i64
        %321 = arith.cmpi eq, %314, %322 : i64
        cf.cond_br %321, ^bb45, ^bb46
        ^bb45:
          %323 = arith.constant 1 : i32
          %325 = arith.extsi %323 : i32 to i64
          %324 = arith.addi %302, %325 : i64
          %326 = llvm.mlir.addressof @MOD : !llvm.ptr
          %327 = llvm.load %326 : !llvm.ptr -> i64
          %328 = arith.remsi %324, %327 : i64
          llvm.store %328, %319 : i64, !llvm.ptr
          cf.br ^bb47
        ^bb46:
          %330 = arith.constant 1 : i32
          %332 = arith.extsi %330 : i32 to i64
          %331 = arith.addi %302, %332 : i64
          %333 = llvm.mlir.addressof @MOD : !llvm.ptr
          %334 = llvm.load %333 : !llvm.ptr -> i64
          %329 = func.call @mod_pow(%314, %331, %334) : (i64, i64, i64) -> i64
          %335 = arith.constant 1 : i32
          %337 = arith.extsi %335 : i32 to i64
          %336 = arith.subi %329, %337 : i64
          %338 = llvm.mlir.addressof @MOD : !llvm.ptr
          %339 = llvm.load %338 : !llvm.ptr -> i64
          %340 = arith.addi %336, %339 : i64
          %341 = llvm.mlir.addressof @MOD : !llvm.ptr
          %342 = llvm.load %341 : !llvm.ptr -> i64
          %343 = arith.remsi %340, %342 : i64
          %344 = arith.constant 1 : i32
          %346 = arith.extsi %344 : i32 to i64
          %345 = arith.subi %314, %346 : i64
          %347 = llvm.mlir.addressof @MOD : !llvm.ptr
          %348 = llvm.load %347 : !llvm.ptr -> i64
          %349 = arith.addi %345, %348 : i64
          %350 = llvm.mlir.addressof @MOD : !llvm.ptr
          %351 = llvm.load %350 : !llvm.ptr -> i64
          %352 = arith.remsi %349, %351 : i64
          %354 = llvm.mlir.addressof @MOD : !llvm.ptr
          %355 = llvm.load %354 : !llvm.ptr -> i64
          %353 = func.call @mod_inv(%352, %355) : (i64, i64) -> i64
          %356 = arith.extsi %343 : i64 to i128
          %357 = arith.extsi %353 : i64 to i128
          %359 = arith.trunci %356 : i128 to i64
          %360 = arith.trunci %357 : i128 to i64
          %358 = arith.muli %359, %360 : i64
          %361 = llvm.mlir.addressof @MOD : !llvm.ptr
          %362 = llvm.load %361 : !llvm.ptr -> i64
          %363 = arith.extsi %362 : i64 to i128
          %365 = arith.trunci %363 : i128 to i64
          %364 = arith.remsi %358, %365 : i64
          llvm.store %364, %319 : i64, !llvm.ptr
          cf.br ^bb47
        ^bb47:
        %366 = llvm.load %291 : !llvm.ptr -> i64
        %367 = arith.extsi %366 : i64 to i128
        %368 = llvm.load %319 : !llvm.ptr -> i64
        %369 = arith.extsi %368 : i64 to i128
        %371 = arith.trunci %367 : i128 to i64
        %372 = arith.trunci %369 : i128 to i64
        %370 = arith.muli %371, %372 : i64
        %373 = llvm.mlir.addressof @MOD : !llvm.ptr
        %374 = llvm.load %373 : !llvm.ptr -> i64
        %375 = arith.extsi %374 : i64 to i128
        %377 = arith.trunci %375 : i128 to i64
        %376 = arith.remsi %370, %377 : i64
        llvm.store %376, %291 : i64, !llvm.ptr
        %378 = llvm.load %295 : !llvm.ptr -> i64
        %379 = arith.constant 1 : i32
        %381 = arith.extsi %379 : i32 to i64
        %380 = arith.addi %378, %381 : i64
        llvm.store %380, %295 : i64, !llvm.ptr
        cf.br ^bb42
      ^bb44:
      %382 = llvm.load %277 : !llvm.ptr -> i64
      %383 = llvm.load %291 : !llvm.ptr -> i64
      %384 = arith.addi %382, %383 : i64
      %385 = llvm.mlir.addressof @MOD : !llvm.ptr
      %386 = llvm.load %385 : !llvm.ptr -> i64
      %387 = arith.remsi %384, %386 : i64
      llvm.store %387, %277 : i64, !llvm.ptr
      %388 = llvm.load %281 : !llvm.ptr -> i64
      %389 = arith.extsi %388 : i64 to i128
      %390 = arith.extsi %260 : i64 to i128
      %392 = arith.trunci %389 : i128 to i64
      %393 = arith.trunci %390 : i128 to i64
      %391 = arith.muli %392, %393 : i64
      %394 = llvm.mlir.addressof @MOD : !llvm.ptr
      %395 = llvm.load %394 : !llvm.ptr -> i64
      %396 = arith.extsi %395 : i64 to i128
      %398 = arith.trunci %396 : i128 to i64
      %397 = arith.remsi %391, %398 : i64
      llvm.store %397, %281 : i64, !llvm.ptr
      %399 = llvm.load %285 : !llvm.ptr -> i64
      %400 = arith.constant 1 : i32
      %402 = arith.extsi %400 : i32 to i64
      %401 = arith.addi %399, %402 : i64
      llvm.store %401, %285 : i64, !llvm.ptr
      cf.br ^bb39
    ^bb41:
    %403 = llvm.load %277 : !llvm.ptr -> i64
    %404 = arith.extsi %403 : i64 to i128
    %405 = arith.extsi %271 : i64 to i128
    %407 = arith.trunci %404 : i128 to i64
    %408 = arith.trunci %405 : i128 to i64
    %406 = arith.muli %407, %408 : i64
    %409 = llvm.mlir.addressof @MOD : !llvm.ptr
    %410 = llvm.load %409 : !llvm.ptr -> i64
    %411 = arith.extsi %410 : i64 to i128
    %413 = arith.trunci %411 : i128 to i64
    %412 = arith.remsi %406, %413 : i64
    func.call @free(%58) : (!llvm.ptr) -> ()
    func.call @free(%89) : (!llvm.ptr) -> ()
    func.call @free(%135) : (!llvm.ptr) -> ()
    func.call @free(%140) : (!llvm.ptr) -> ()
    func.call @free(%147) : (!llvm.ptr) -> ()
    %419 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %420 = llvm.call @printf(%419, %412) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %421 = arith.constant 0 : i32
    func.return %421 : i32
  }
}