Problem 627

Distinct products F(30,10001) via Ehrhart cubic * rising factorial.

Answer220196142
Output220196142
StatusPASS
Native helperno
Runtime0 ms
Peak memory1120 KB
Time complexityO(n^3) (estimated)
Space complexityO(n) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^3)O(n)
Space complexityO(n)O(n)
ApproachFlow solutionBig-integer factorial
VerdictSuboptimal

Flow source

# Project Euler 627
# Distinct products F(30,10001) via Ehrhart cubic * rising factorial.

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

const MOD: i64 = 1000000007

function modpow(base0: i64, exp0: i64, mod: i64) -> i64 {
    let mut r: i64 = 1
    let mut b: i64 = base0 % mod
    let mut e: i64 = exp0
    while e > 0 {
        if (e & 1) == 1 {
            let t: i128 = (r as i128) * (b as i128) % (mod as i128)
            r = t as i64
        }
        let t2: i128 = (b as i128) * (b as i128) % (mod as i128)
        b = t2 as i64
        e = e / 2
    }
    return r
}

function modinv(a: i64) -> i64 {
    return modpow(a % MOD, MOD - 2, MOD)
}

function rising_mod(a0: i64, k: i64) -> i64 {
    let mut res: i64 = 1
    let mut a: i64 = a0 % MOD
    let mut i: i64 = 0
    while i < k {
        res = (res * ((a + i) % MOD)) % MOD
        i = i + 1
    }
    return res
}

function eval_cubic(f0: i64, f1: i64, f2: i64, f3: i64, n0: i64) -> i64 {
    let mut d1: i64 = (f1 - f0) % MOD
    if d1 < 0 { d1 = d1 + MOD }
    let mut d2: i64 = (f2 - 2 * (f1 % MOD) + f0) % MOD
    if d2 < 0 { d2 = d2 + MOD }
    let mut d3: i64 = (f3 - 3 * (f2 % MOD) + 3 * (f1 % MOD) - f0) % MOD
    if d3 < 0 { d3 = d3 + MOD }
    let n: i64 = n0 % MOD
    let c1: i64 = n
    let c2: i64 = n * ((n - 1 + MOD) % MOD) % MOD * modinv(2) % MOD
    let c3: i64 = n * ((n - 1 + MOD) % MOD) % MOD * ((n - 2 + MOD) % MOD) % MOD * modinv(6) % MOD
    return (f0 + d1 * c1 % MOD + d2 * c2 % MOD + d3 * c3 % MOD) % MOD
}

function main() -> i32 {
    let maxp: i64 = 30 * 30 * 30
    let cur: ptr<i8> = calloc(maxp + 1, 1)
    let nxt: ptr<i8> = calloc(maxp + 1, 1)
    let F: ptr<i64> = calloc(4, 8)
    if cur == null || nxt == null || F == null { return 1 }
    cur[1] = 1
    F[0] = 1
    let mut s: i64 = 1
    while s <= 3 {
        let mut x: i64 = 0
        while x <= maxp {
            nxt[x] = 0
            x = x + 1
        }
        x = 1
        while x <= maxp {
            if cur[x] != 0 {
                let mut m: i64 = 1
                while m <= 30 {
                    let y: i64 = x * m
                    if y <= maxp {
                        nxt[y] = 1
                    }
                    m = m + 1
                }
            }
            x = x + 1
        }
        let tmp: ptr<i8> = cur
        cur = nxt
        nxt = tmp
        let mut cnt: i64 = 0
        x = 1
        while x <= maxp {
            if cur[x] != 0 { cnt = cnt + 1 }
            x = x + 1
        }
        F[s] = cnt
        s = s + 1
    }
    let c0: i64 = F[0] * modinv(rising_mod(1, 7)) % MOD
    let c1: i64 = F[1] * modinv(rising_mod(2, 7)) % MOD
    let c2: i64 = F[2] * modinv(rising_mod(3, 7)) % MOD
    let c3: i64 = F[3] * modinv(rising_mod(4, 7)) % MOD
    let n: i64 = 10001
    let c_at: i64 = eval_cubic(c0, c1, c2, c3, n)
    let ans: i64 = rising_mod(n + 1, 7) * c_at % MOD
    printf("%lld\n", ans)
    free(cur)
    free(nxt)
    free(F)
    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 modpow_i64_i64_i64(int64_t base0, int64_t exp0, int64_t mod);
int64_t modinv_i64(int64_t a);
int64_t rising_mod_i64_i64(int64_t a0, int64_t k);
int64_t eval_cubic_i64_i64_i64_i64_i64(int64_t f0, int64_t f1, int64_t f2, int64_t f3, int64_t n0);
int32_t main(void);

static const int64_t MOD = 1000000007;



int64_t modpow_i64_i64_i64(int64_t base0, int64_t exp0, int64_t mod) {
    int64_t r = 1;
    int64_t b = FLOW_CHECKED_MOD((base0), (mod));
    int64_t e = exp0;
    while (e > 0) {
        if ((e & 1) == 1) {
            __int128 t = FLOW_CHECKED_MOD(((((__int128)(r)) * ((__int128)(b)))), (((__int128)(mod))));
            r = ((int64_t)(t));
        }
        __int128 t2 = FLOW_CHECKED_MOD(((((__int128)(b)) * ((__int128)(b)))), (((__int128)(mod))));
        b = ((int64_t)(t2));
        e = FLOW_CHECKED_DIV((e), (2));
    }
    return r;
}

int64_t modinv_i64(int64_t a) {
    return modpow_i64_i64_i64(FLOW_CHECKED_MOD((a), (MOD)), (MOD - 2), MOD);
}

int64_t rising_mod_i64_i64(int64_t a0, int64_t k) {
    int64_t res = 1;
    int64_t a = FLOW_CHECKED_MOD((a0), (MOD));
    int64_t i = 0;
    while (i < k) {
        res = FLOW_CHECKED_MOD(((res * FLOW_CHECKED_MOD(((a + i)), (MOD)))), (MOD));
        i = (i + 1);
    }
    return res;
}

int64_t eval_cubic_i64_i64_i64_i64_i64(int64_t f0, int64_t f1, int64_t f2, int64_t f3, int64_t n0) {
    int64_t d1 = FLOW_CHECKED_MOD(((f1 - f0)), (MOD));
    if (d1 < 0) {
        d1 = (d1 + MOD);
    }
    int64_t d2 = FLOW_CHECKED_MOD((((f2 - (2 * FLOW_CHECKED_MOD((f1), (MOD)))) + f0)), (MOD));
    if (d2 < 0) {
        d2 = (d2 + MOD);
    }
    int64_t d3 = FLOW_CHECKED_MOD(((((f3 - (3 * FLOW_CHECKED_MOD((f2), (MOD)))) + (3 * FLOW_CHECKED_MOD((f1), (MOD)))) - f0)), (MOD));
    if (d3 < 0) {
        d3 = (d3 + MOD);
    }
    int64_t n = FLOW_CHECKED_MOD((n0), (MOD));
    int64_t c1 = n;
    int64_t c2 = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD(((n * FLOW_CHECKED_MOD((((n - 1) + MOD)), (MOD)))), (MOD)) * modinv_i64(2))), (MOD));
    int64_t c3 = FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD(((FLOW_CHECKED_MOD(((n * FLOW_CHECKED_MOD((((n - 1) + MOD)), (MOD)))), (MOD)) * FLOW_CHECKED_MOD((((n - 2) + MOD)), (MOD)))), (MOD)) * modinv_i64(6))), (MOD));
    return FLOW_CHECKED_MOD(((((f0 + FLOW_CHECKED_MOD(((d1 * c1)), (MOD))) + FLOW_CHECKED_MOD(((d2 * c2)), (MOD))) + FLOW_CHECKED_MOD(((d3 * c3)), (MOD)))), (MOD));
}

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