Problem 802

P(n) = sum_{d<=n} A(d) * M(floor(n/d)) mod 1020340567, n = 10^7. A(1)=2, A(d)=2^(d-1). M is the Mertens function. Floor-division grouping. Pure Flow port of the native C solver. Uses i128 for mod_pow intermediates.

Answer973873727
Output973873727
StatusPASS
Native helperno
Runtime50 ms
Peak memory94352 KB
Time complexityO(n) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n)O(n * m)
Space complexityO(n^2)O(n)
ApproachFlow solutionDynamic programming or generating function
VerdictUnknown

Flow source

# Project Euler 802: Iterated Composition.
# P(n) = sum_{d<=n} A(d) * M(floor(n/d)) mod 1020340567, n = 10^7.
# A(1)=2, A(d)=2^(d-1). M is the Mertens function. Floor-division grouping.
# Pure Flow port of the native C solver. Uses i128 for mod_pow intermediates.

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

const MOD: i64 = 1020340567
const N_DEFAULT: i64 = 10000000

function mod_pow(a0: i64, e0: i64, modv: i64) -> i64 {
    let mut r: i128 = 1 % (modv as i128)
    let mut a: i128 = a0 % (modv as i128)
    let mut e: i64 = e0
    while e > 0 {
        if e % 2 == 1 {
            r = r * a % (modv as i128)
        }
        a = a * a % (modv as i128)
        e = e / 2
    }
    return r as i64
}

# Build sorted ascending distinct values of floor(n / k) for k=1..n.
function build_floor_div_queries(n: i64, qs: ptr<i64>) -> i64 {
    let mut cnt: i64 = 0
    let mut k: i64 = 1
    while k <= n {
        let q: i64 = n / k
        qs[cnt] = q
        cnt = cnt + 1
        k = n / q + 1
    }
    # qs is strictly decreasing; reverse to ascending.
    let mut i: i64 = 0
    let mut j: i64 = cnt - 1
    while i < j {
        let t: i64 = qs[i]
        qs[i] = qs[j]
        qs[j] = t
        i = i + 1
        j = j - 1
    }
    return cnt
}

# Compute Mertens M(t) at the selected ascending query points via linear sieve.
function mertens_at_points(n: i64, points: ptr<i64>, npoints: i64, res: ptr<i64>) -> void {
    if npoints == 0 {
        return
    }
    let mu: ptr<i8> = calloc(n + 1, 1) as ptr<i8>
    let lp: ptr<i64> = calloc(n + 1, 8) as ptr<i64>
    let primes: ptr<i64> = calloc(n, 8) as ptr<i64>
    let mut nprimes: i64 = 0

    mu[1] = 1
    let mut mertens: i64 = 1
    let mut idx: i64 = 0
    if points[0] == 1 {
        res[0] = 1
        idx = 1
    }

    let mut i: i64 = 2
    while i <= n {
        if lp[i] == 0 {
            lp[i] = i
            primes[nprimes] = i
            nprimes = nprimes + 1
            mu[i] = -1
        }
        let li: i64 = lp[i]
        let mui: i8 = mu[i]
        let mut pi: i64 = 0
        while pi < nprimes {
            let p: i64 = primes[pi]
            if p > li {
                pi = nprimes
            } else {
                let ip: i64 = i * p
                if ip > n {
                    pi = nprimes
                } else {
                    lp[ip] = p
                    if p == li {
                        mu[ip] = 0
                        pi = nprimes
                    } else {
                        mu[ip] = -mui
                    }
                    pi = pi + 1
                }
            }
        }
        mertens = mertens + (mu[i] as i64)
        if idx < npoints && i == points[idx] {
            res[idx] = mertens
            idx = idx + 1
        }
        i = i + 1
    }

    free(mu)
    free(lp)
    free(primes)
}

# Sum_{d=l..r} A(d) mod MOD, A(1)=2, A(d)=2^(d-1) for d>=2.
function sum_A(l: i64, r: i64) -> i64 {
    if l == 1 {
        return mod_pow(2, r, MOD)
    }
    let mut v: i64 = (mod_pow(2, r, MOD) - mod_pow(2, l - 1, MOD)) % MOD
    if v < 0 {
        v = v + MOD
    }
    return v
}

function P_mod(n: i64) -> i64 {
    if n <= 0 {
        return 0
    }
    let qs: ptr<i64> = calloc(2 * 64000, 8) as ptr<i64>
    let nq: i64 = build_floor_div_queries(n, qs)
    let mertens: ptr<i64> = calloc(nq, 8) as ptr<i64>
    mertens_at_points(n, qs, nq, mertens)

    let mut ans: i64 = 0
    let mut l: i64 = 1
    while l <= n {
        let q: i64 = n / l
        let r: i64 = n / q
        # binary search for q in ascending qs
        let mut lo: i64 = 0
        let mut hi: i64 = nq - 1
        let mut found: i64 = -1
        while lo <= hi {
            let mid: i64 = (lo + hi) / 2
            if qs[mid] == q {
                found = mid
                lo = hi + 1
            } else {
                if qs[mid] < q {
                    lo = mid + 1
                } else {
                    hi = mid - 1
                }
            }
        }
        let m: i64 = mertens[found]
        let s: i64 = sum_A(l, r)
        let term: i128 = (s as i128) * (m as i128) % (MOD as i128)
        ans = (ans + (term as i64)) % MOD
        if ans < 0 {
            ans = ans + MOD
        }
        l = r + 1
    }

    free(qs)
    free(mertens)
    return ans
}

function main() -> i32 {
    printf("%lld\n", P_mod(N_DEFAULT))
    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 a0, int64_t e0, int64_t modv);
int64_t build_floor_div_queries_i64_ptr_i64(int64_t n, int64_t* qs);
void mertens_at_points_i64_ptr_i64_i64_ptr_i64(int64_t n, int64_t* points, int64_t npoints, int64_t* res);
int64_t sum_A_i64_i64(int64_t l, int64_t r);
int64_t P_mod_i64(int64_t n);
int32_t main(void);

static const int64_t MOD = 1020340567;
static const int64_t N_DEFAULT = 10000000;



int64_t mod_pow_i64_i64_i64(int64_t a0, int64_t e0, int64_t modv) {
    __int128 r = FLOW_CHECKED_MOD((1), (((__int128)(modv))));
    __int128 a = FLOW_CHECKED_MOD((a0), (((__int128)(modv))));
    int64_t e = e0;
    while (e > 0) {
        if (FLOW_CHECKED_MOD((e), (2)) == 1) {
            r = FLOW_CHECKED_MOD(((r * a)), (((__int128)(modv))));
        }
        a = FLOW_CHECKED_MOD(((a * a)), (((__int128)(modv))));
        e = FLOW_CHECKED_DIV((e), (2));
    }
    return ((int64_t)(r));
}

int64_t build_floor_div_queries_i64_ptr_i64(int64_t n, int64_t* qs) {
    int64_t cnt = 0;
    int64_t k = 1;
    while (k <= n) {
        int64_t q = FLOW_CHECKED_DIV((n), (k));
        qs[cnt] = q;
        cnt = (cnt + 1);
        k = (FLOW_CHECKED_DIV((n), (q)) + 1);
    }
    int64_t i = 0;
    int64_t j = (cnt - 1);
    while (i < j) {
        int64_t t = qs[i];
        qs[i] = qs[j];
        qs[j] = t;
        i = (i + 1);
        j = (j - 1);
    }
    return cnt;
}

void mertens_at_points_i64_ptr_i64_i64_ptr_i64(int64_t n, int64_t* points, int64_t npoints, int64_t* res) {
    if (npoints == 0) {
        return;
    }
    int8_t* mu = (int8_t*)(((int8_t*)(calloc((n + 1), 1))));
    int64_t* lp = (int64_t*)(((int64_t*)(calloc((n + 1), 8))));
    int64_t* primes = (int64_t*)(((int64_t*)(calloc(n, 8))));
    int64_t nprimes = 0;
    mu[1] = 1;
    int64_t mertens = 1;
    int64_t idx = 0;
    if (points[0] == 1) {
        res[0] = 1;
        idx = 1;
    }
    int64_t i = 2;
    while (i <= n) {
        if (lp[i] == 0) {
            lp[i] = i;
            primes[nprimes] = i;
            nprimes = (nprimes + 1);
            mu[i] = (-1);
        }
        int64_t li = lp[i];
        int8_t mui = mu[i];
        int64_t pi = 0;
        while (pi < nprimes) {
            int64_t p = primes[pi];
            if (p > li) {
                pi = nprimes;
            } else {
                int64_t ip = (i * p);
                if (ip > n) {
                    pi = nprimes;
                } else {
                    lp[ip] = p;
                    if (p == li) {
                        mu[ip] = 0;
                        pi = nprimes;
                    } else {
                        mu[ip] = (-mui);
                    }
                    pi = (pi + 1);
                }
            }
        }
        mertens = (mertens + ((int64_t)(mu[i])));
        if ((idx < npoints && i == points[idx])) {
            res[idx] = mertens;
            idx = (idx + 1);
        }
        i = (i + 1);
    }
    free(mu);
    free(lp);
    free(primes);
}

int64_t sum_A_i64_i64(int64_t l, int64_t r) {
    if (l == 1) {
        return mod_pow_i64_i64_i64(2, r, MOD);
    }
    int64_t v = FLOW_CHECKED_MOD(((mod_pow_i64_i64_i64(2, r, MOD) - mod_pow_i64_i64_i64(2, (l - 1), MOD))), (MOD));
    if (v < 0) {
        v = (v + MOD);
    }
    return v;
}

int64_t P_mod_i64(int64_t n) {
    if (n <= 0) {
        return 0;
    }
    int64_t* qs = (int64_t*)(((int64_t*)(calloc((2 * 64000), 8))));
    int64_t nq = build_floor_div_queries_i64_ptr_i64(n, qs);
    int64_t* mertens = (int64_t*)(((int64_t*)(calloc(nq, 8))));
    mertens_at_points_i64_ptr_i64_i64_ptr_i64(n, qs, nq, mertens);
    int64_t ans = 0;
    int64_t l = 1;
    while (l <= n) {
        int64_t q = FLOW_CHECKED_DIV((n), (l));
        int64_t r = FLOW_CHECKED_DIV((n), (q));
        int64_t lo = 0;
        int64_t hi = (nq - 1);
        int64_t found = (-1);
        while (lo <= hi) {
            int64_t mid = FLOW_CHECKED_DIV(((lo + hi)), (2));
            if (qs[mid] == q) {
                found = mid;
                lo = (hi + 1);
            } else {
                if (qs[mid] < q) {
                    lo = (mid + 1);
                } else {
                    hi = (mid - 1);
                }
            }
        }
        int64_t m = mertens[found];
        int64_t s = sum_A_i64_i64(l, r);
        __int128 term = FLOW_CHECKED_MOD(((((__int128)(s)) * ((__int128)(m)))), (((__int128)(MOD))));
        ans = FLOW_CHECKED_MOD(((ans + ((int64_t)(term)))), (MOD));
        if (ans < 0) {
            ans = (ans + MOD);
        }
        l = (r + 1);
    }
    free(qs);
    free(mertens);
    return ans;
}

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