Problem 811

H(t, r) = A((2^t + 1)^r) mod 1000062031 with t = 10^14 + 31, r = 62.

Answer327287526
Output327287526
StatusPASS
Native helperno
Runtime0 ms
Peak memory1104 KB
Time complexityO(n^3) (estimated)
Space complexityO(n) (estimated)

Performance comparison

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

Flow source

# Project Euler 811: Bitwise Recursion
# H(t, r) = A((2^t + 1)^r) mod 1000062031
# with t = 10^14 + 31, r = 62.

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

const MOD: i64 = 1000062031

# Positions of 1-bits in (2^t + 1)^r using the binomial block method.
# Assumes t >= max_binom_bitlen(r) so blocks don't overlap.
# Returns positions in increasing order.
function one_positions_via_binom(t: i64, r: i32, pos_out: ptr<i64>) -> i32 {
    let mut cnt: i32 = 0
    let mut c: i128 = 1 as i128
    let mut k: i32 = 0
    while k <= r {
        let mut x: i128 = c
        while x != (0 as i128) {
            let lsb: i128 = x & ((0 as i128) - x)
            let mut bit: i32 = 0
            let mut tmp: i128 = lsb
            while tmp > (1 as i128) {
                tmp = tmp >> (1 as i128)
                bit = bit + 1
            }
            pos_out[cnt] = (k as i64) * t + (bit as i64)
            cnt = cnt + 1
            x = x - lsb
        }
        if k < r {
            c = c * ((r - k) as i128) / ((k + 1) as i128)
        }
        k = k + 1
    }
    return cnt
}

function powmod(base0: i64, exp0: i64, mod: i64) -> i64 {
    let mut r: i64 = 1 % mod
    let mut b: i64 = base0 % mod
    if b < 0 {
        b = b + mod
    }
    let mut e: i64 = exp0
    while e > 0 {
        if (e & 1) == 1 {
            r = (((r as i128) * (b as i128)) % (mod as i128)) as i64
        }
        b = (((b as i128) * (b as i128)) % (mod as i128)) as i64
        e = e >> 1
    }
    return r
}

# Compute A(n) given positions of 1-bits in n (sorted increasing), mod MOD
function A_from_positions(pos: ptr<i64>, m: i32, mod: i64) -> i64 {
    if m == 0 {
        return 0
    }
    if m == 1 {
        return 1 % mod
    }

    let v: ptr<i64> = calloc((m as i64), 8)
    v[0] = 1 % mod
    let mut k: i32 = 1
    while k < m {
        v[k] = (5 * v[k - 1] + 3) % mod
        k = k + 1
    }

    let mut ans: i64 = 1 % mod
    let mut i: i32 = 0
    while i < m - 1 {
        let gap: i64 = pos[(m - 1 - i) as i64] - pos[(m - 1 - i - 1) as i64] - 1
        if gap <= 0 {
            i = i + 1
            continue
        }
        let base: i64 = v[(i + 1) as i64]
        ans = (ans * powmod(base, gap, mod)) % mod
        i = i + 1
    }

    free(v)
    return ans
}

function main() -> i32 {
    let t: i64 = 100000000000031
    let r: i32 = 62

    let maxbits: i32 = 4000
    let pos: ptr<i64> = calloc((maxbits as i64), 8)
    let npos: i32 = one_positions_via_binom(t, r, pos)

    let result: i64 = A_from_positions(pos, npos, MOD)

    free(pos)
    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; }

int32_t one_positions_via_binom_i64_i32_ptr_i64(int64_t t, int32_t r, int64_t* pos_out);
int64_t powmod_i64_i64_i64(int64_t base0, int64_t exp0, int64_t mod);
int64_t A_from_positions_ptr_i64_i32_i64(int64_t* pos, int32_t m, int64_t mod);
int32_t main(void);

static const int64_t MOD = 1000062031;



int32_t one_positions_via_binom_i64_i32_ptr_i64(int64_t t, int32_t r, int64_t* pos_out) {
    int32_t cnt = 0;
    __int128 c = ((__int128)(1));
    int32_t k = 0;
    while (k <= r) {
        __int128 x = c;
        while (x != ((__int128)(0))) {
            __int128 lsb = (x & (((__int128)(0)) - x));
            int32_t bit = 0;
            __int128 tmp = lsb;
            while (tmp > ((__int128)(1))) {
                tmp = FLOW_CHECKED_SHR((tmp), (((__int128)(1))));
                bit = (bit + 1);
            }
            pos_out[cnt] = ((((int64_t)(k)) * t) + ((int64_t)(bit)));
            cnt = (cnt + 1);
            x = (x - lsb);
        }
        if (k < r) {
            c = FLOW_CHECKED_DIV(((c * ((__int128)((r - k))))), (((__int128)((k + 1)))));
        }
        k = (k + 1);
    }
    return cnt;
}

int64_t powmod_i64_i64_i64(int64_t base0, int64_t exp0, int64_t mod) {
    int64_t r = FLOW_CHECKED_MOD((1), (mod));
    int64_t b = FLOW_CHECKED_MOD((base0), (mod));
    if (b < 0) {
        b = (b + mod);
    }
    int64_t e = exp0;
    while (e > 0) {
        if ((e & 1) == 1) {
            r = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(r)) * ((__int128)(b)))), (((__int128)(mod))))));
        }
        b = ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(b)) * ((__int128)(b)))), (((__int128)(mod))))));
        e = FLOW_CHECKED_SHR((e), (1));
    }
    return r;
}

int64_t A_from_positions_ptr_i64_i32_i64(int64_t* pos, int32_t m, int64_t mod) {
    if (m == 0) {
        return 0;
    }
    if (m == 1) {
        return FLOW_CHECKED_MOD((1), (mod));
    }
    int64_t* v = (int64_t*)(calloc(((int64_t)(m)), 8));
    v[0] = FLOW_CHECKED_MOD((1), (mod));
    int32_t k = 1;
    while (k < m) {
        v[k] = FLOW_CHECKED_MOD((((5 * v[(k - 1)]) + 3)), (mod));
        k = (k + 1);
    }
    int64_t ans = FLOW_CHECKED_MOD((1), (mod));
    int32_t i = 0;
    while (i < (m - 1)) {
        int64_t gap = ((pos[((int64_t)(((m - 1) - i)))] - pos[((int64_t)((((m - 1) - i) - 1)))]) - 1);
        if (gap <= 0) {
            i = (i + 1);
            continue;
        }
        int64_t base = v[((int64_t)((i + 1)))];
        ans = FLOW_CHECKED_MOD(((ans * powmod_i64_i64_i64(base, gap, mod))), (mod));
        i = (i + 1);
    }
    free(v);
    return ans;
}

int32_t main(void) {
    int64_t t = 100000000000031;
    int32_t r = 62;
    int32_t maxbits = 4000;
    int64_t* pos = (int64_t*)(calloc(((int64_t)(maxbits)), 8));
    int32_t npos = one_positions_via_binom_i64_i32_ptr_i64(t, r, pos);
    int64_t result = A_from_positions_ptr_i64_i32_i64(pos, npos, MOD);
    free(pos);
    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) -> ()
  // Constant: MOD
  llvm.mlir.global internal constant @MOD(1000062031 : i64) : i64
  func.func @one_positions_via_binom(%arg0: i64, %arg1: i32, %arg2: !llvm.ptr) -> i32 {
    %0 = arith.constant 0 : i32
    %1 = llvm.mlir.constant(1 : i64) : i64
    %2 = llvm.alloca %1 x i32 : (i64) -> !llvm.ptr
    llvm.store %0, %2 : i32, !llvm.ptr
    %3 = arith.constant 1 : i32
    %4 = arith.extsi %3 : i32 to i128
    %5 = llvm.mlir.constant(1 : i64) : i64
    %6 = llvm.alloca %5 x i128 : (i64) -> !llvm.ptr
    llvm.store %4, %6 : i128, !llvm.ptr
    %7 = arith.constant 0 : i32
    %8 = llvm.mlir.constant(1 : i64) : i64
    %9 = llvm.alloca %8 x i32 : (i64) -> !llvm.ptr
    llvm.store %7, %9 : i32, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %10 = llvm.load %9 : !llvm.ptr -> i32
    %11 = arith.cmpi sle, %10, %arg1 : i32
    cf.cond_br %11, ^bb1, ^bb2
    ^bb1:
      %12 = llvm.load %6 : !llvm.ptr -> i128
      %13 = llvm.mlir.constant(1 : i64) : i64
      %14 = llvm.alloca %13 x i128 : (i64) -> !llvm.ptr
      llvm.store %12, %14 : i128, !llvm.ptr
      cf.br ^bb3
      ^bb3:
      %15 = llvm.load %14 : !llvm.ptr -> i128
      %16 = arith.constant 0 : i32
      %17 = arith.extsi %16 : i32 to i128
      %19 = arith.trunci %15 : i128 to i64
      %20 = arith.trunci %17 : i128 to i64
      %18 = arith.cmpi ne, %19, %20 : i64
      cf.cond_br %18, ^bb4, ^bb5
      ^bb4:
        %21 = llvm.load %14 : !llvm.ptr -> i128
        %22 = arith.constant 0 : i32
        %23 = arith.extsi %22 : i32 to i128
        %24 = llvm.load %14 : !llvm.ptr -> i128
        %26 = arith.trunci %23 : i128 to i64
        %27 = arith.trunci %24 : i128 to i64
        %25 = arith.subi %26, %27 : i64
        %29 = arith.trunci %21 : i128 to i64
        %28 = arith.andi %29, %25 : i64
        %30 = arith.extsi %28 : i64 to i128
        %31 = arith.constant 0 : i32
        %32 = llvm.mlir.constant(1 : i64) : i64
        %33 = llvm.alloca %32 x i32 : (i64) -> !llvm.ptr
        llvm.store %31, %33 : i32, !llvm.ptr
        %34 = llvm.mlir.constant(1 : i64) : i64
        %35 = llvm.alloca %34 x i128 : (i64) -> !llvm.ptr
        llvm.store %30, %35 : i128, !llvm.ptr
        cf.br ^bb6
        ^bb6:
        %36 = llvm.load %35 : !llvm.ptr -> i128
        %37 = arith.constant 1 : i32
        %38 = arith.extsi %37 : i32 to i128
        %40 = arith.trunci %36 : i128 to i64
        %41 = arith.trunci %38 : i128 to i64
        %39 = arith.cmpi sgt, %40, %41 : i64
        cf.cond_br %39, ^bb7, ^bb8
        ^bb7:
          %42 = llvm.load %35 : !llvm.ptr -> i128
          %43 = arith.constant 1 : i32
          %44 = arith.extsi %43 : i32 to i128
          %46 = arith.trunci %42 : i128 to i64
          %47 = arith.trunci %44 : i128 to i64
          %45 = arith.shrsi %46, %47 : i64
          %48 = arith.extsi %45 : i64 to i128
          llvm.store %48, %35 : i128, !llvm.ptr
          %49 = llvm.load %33 : !llvm.ptr -> i32
          %50 = arith.constant 1 : i32
          %51 = arith.addi %49, %50 : i32
          llvm.store %51, %33 : i32, !llvm.ptr
          cf.br ^bb6
        ^bb8:
        %52 = llvm.load %9 : !llvm.ptr -> i32
        %53 = arith.extsi %52 : i32 to i64
        %54 = arith.muli %53, %arg0 : i64
        %55 = llvm.load %33 : !llvm.ptr -> i32
        %56 = arith.extsi %55 : i32 to i64
        %57 = arith.addi %54, %56 : i64
        %58 = llvm.load %2 : !llvm.ptr -> i32
        %59 = arith.extsi %58 : i32 to i64
        %60 = llvm.getelementptr %arg2[%59] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %57, %60 : i64, !llvm.ptr
        %61 = llvm.load %2 : !llvm.ptr -> i32
        %62 = arith.constant 1 : i32
        %63 = arith.addi %61, %62 : i32
        llvm.store %63, %2 : i32, !llvm.ptr
        %64 = llvm.load %14 : !llvm.ptr -> i128
        %66 = arith.trunci %64 : i128 to i64
        %67 = arith.trunci %30 : i128 to i64
        %65 = arith.subi %66, %67 : i64
        %68 = arith.extsi %65 : i64 to i128
        llvm.store %68, %14 : i128, !llvm.ptr
        cf.br ^bb3
      ^bb5:
      %69 = llvm.load %9 : !llvm.ptr -> i32
      %70 = arith.cmpi slt, %69, %arg1 : i32
      cf.cond_br %70, ^bb9, ^bb10
      ^bb9:
        %71 = llvm.load %6 : !llvm.ptr -> i128
        %72 = llvm.load %9 : !llvm.ptr -> i32
        %73 = arith.subi %arg1, %72 : i32
        %74 = arith.extsi %73 : i32 to i128
        %76 = arith.trunci %71 : i128 to i64
        %77 = arith.trunci %74 : i128 to i64
        %75 = arith.muli %76, %77 : i64
        %78 = llvm.load %9 : !llvm.ptr -> i32
        %79 = arith.constant 1 : i32
        %80 = arith.addi %78, %79 : i32
        %81 = arith.extsi %80 : i32 to i128
        %83 = arith.trunci %81 : i128 to i64
        %82 = arith.divsi %75, %83 : i64
        %84 = arith.extsi %82 : i64 to i128
        llvm.store %84, %6 : i128, !llvm.ptr
        cf.br ^bb11
      ^bb10:
        cf.br ^bb11
      ^bb11:
      %85 = llvm.load %9 : !llvm.ptr -> i32
      %86 = arith.constant 1 : i32
      %87 = arith.addi %85, %86 : i32
      llvm.store %87, %9 : i32, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    %88 = llvm.load %2 : !llvm.ptr -> i32
    func.return %88 : i32
  }
  func.func @powmod(%arg0: i64, %arg1: i64, %arg2: i64) -> i64 {
    %89 = arith.constant 1 : i32
    %91 = arith.extsi %89 : i32 to i64
    %90 = arith.remsi %91, %arg2 : i64
    %92 = llvm.mlir.constant(1 : i64) : i64
    %93 = llvm.alloca %92 x i64 : (i64) -> !llvm.ptr
    llvm.store %90, %93 : i64, !llvm.ptr
    %94 = arith.remsi %arg0, %arg2 : 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, ^bb12, ^bb13
    ^bb12:
      %101 = llvm.load %96 : !llvm.ptr -> i64
      %102 = arith.addi %101, %arg2 : i64
      llvm.store %102, %96 : i64, !llvm.ptr
      cf.br ^bb14
    ^bb13:
      cf.br ^bb14
    ^bb14:
    %103 = llvm.mlir.constant(1 : i64) : i64
    %104 = llvm.alloca %103 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %104 : i64, !llvm.ptr
    cf.br ^bb15
    ^bb15:
    %105 = llvm.load %104 : !llvm.ptr -> i64
    %106 = arith.constant 0 : i32
    %108 = arith.extsi %106 : i32 to i64
    %107 = arith.cmpi sgt, %105, %108 : i64
    cf.cond_br %107, ^bb16, ^bb17
    ^bb16:
      %109 = llvm.load %104 : !llvm.ptr -> i64
      %110 = arith.constant 1 : i32
      %112 = arith.extsi %110 : i32 to i64
      %111 = arith.andi %109, %112 : i64
      %113 = arith.constant 1 : i32
      %115 = arith.extsi %113 : i32 to i64
      %114 = arith.cmpi eq, %111, %115 : i64
      cf.cond_br %114, ^bb18, ^bb19
      ^bb18:
        %116 = llvm.load %93 : !llvm.ptr -> i64
        %117 = arith.extsi %116 : i64 to i128
        %118 = llvm.load %96 : !llvm.ptr -> i64
        %119 = arith.extsi %118 : i64 to i128
        %121 = arith.trunci %117 : i128 to i64
        %122 = arith.trunci %119 : i128 to i64
        %120 = arith.muli %121, %122 : i64
        %123 = arith.extsi %arg2 : i64 to i128
        %125 = arith.trunci %123 : i128 to i64
        %124 = arith.remsi %120, %125 : i64
        llvm.store %124, %93 : i64, !llvm.ptr
        cf.br ^bb20
      ^bb19:
        cf.br ^bb20
      ^bb20:
      %126 = llvm.load %96 : !llvm.ptr -> i64
      %127 = arith.extsi %126 : i64 to i128
      %128 = llvm.load %96 : !llvm.ptr -> i64
      %129 = arith.extsi %128 : i64 to i128
      %131 = arith.trunci %127 : i128 to i64
      %132 = arith.trunci %129 : i128 to i64
      %130 = arith.muli %131, %132 : i64
      %133 = arith.extsi %arg2 : i64 to i128
      %135 = arith.trunci %133 : i128 to i64
      %134 = arith.remsi %130, %135 : i64
      llvm.store %134, %96 : i64, !llvm.ptr
      %136 = llvm.load %104 : !llvm.ptr -> i64
      %137 = arith.constant 1 : i32
      %139 = arith.extsi %137 : i32 to i64
      %138 = arith.shrsi %136, %139 : i64
      llvm.store %138, %104 : i64, !llvm.ptr
      cf.br ^bb15
    ^bb17:
    %140 = llvm.load %93 : !llvm.ptr -> i64
    func.return %140 : i64
  }
  func.func @A_from_positions(%arg0: !llvm.ptr, %arg1: i32, %arg2: i64) -> i64 {
    %141 = arith.constant 0 : i32
    %142 = arith.cmpi eq, %arg1, %141 : i32
    cf.cond_br %142, ^bb21, ^bb22
    ^bb21:
      %143 = arith.constant 0 : i32
      %144 = arith.extsi %143 : i32 to i64
      func.return %144 : i64
    ^bb22:
      cf.br ^bb23
    ^bb23:
    %145 = arith.constant 1 : i32
    %146 = arith.cmpi eq, %arg1, %145 : i32
    cf.cond_br %146, ^bb24, ^bb25
    ^bb24:
      %147 = arith.constant 1 : i32
      %149 = arith.extsi %147 : i32 to i64
      %148 = arith.remsi %149, %arg2 : i64
      func.return %148 : i64
    ^bb25:
      cf.br ^bb26
    ^bb26:
    %151 = arith.extsi %arg1 : i32 to i64
    %152 = arith.constant 8 : i32
    %153 = arith.extsi %152 : i32 to i64
    %150 = func.call @calloc(%151, %153) : (i64, i64) -> !llvm.ptr
    %154 = arith.constant 1 : i32
    %156 = arith.extsi %154 : i32 to i64
    %155 = arith.remsi %156, %arg2 : i64
    %157 = arith.constant 0 : i32
    %158 = arith.extsi %157 : i32 to i64
    %159 = llvm.getelementptr %150[%158] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %155, %159 : i64, !llvm.ptr
    %160 = arith.constant 1 : i32
    %161 = llvm.mlir.constant(1 : i64) : i64
    %162 = llvm.alloca %161 x i32 : (i64) -> !llvm.ptr
    llvm.store %160, %162 : i32, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %163 = llvm.load %162 : !llvm.ptr -> i32
    %164 = arith.cmpi slt, %163, %arg1 : i32
    cf.cond_br %164, ^bb28, ^bb29
    ^bb28:
      %165 = arith.constant 5 : i32
      %167 = llvm.load %162 : !llvm.ptr -> i32
      %168 = arith.constant 1 : i32
      %169 = arith.subi %167, %168 : i32
      %170 = arith.extsi %169 : i32 to i64
      %171 = llvm.getelementptr %150[%170] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %166 = llvm.load %171 : !llvm.ptr -> i64
      %173 = arith.extsi %165 : i32 to i64
      %172 = arith.muli %173, %166 : i64
      %174 = arith.constant 3 : i32
      %176 = arith.extsi %174 : i32 to i64
      %175 = arith.addi %172, %176 : i64
      %177 = arith.remsi %175, %arg2 : i64
      %178 = llvm.load %162 : !llvm.ptr -> i32
      %179 = arith.extsi %178 : i32 to i64
      %180 = llvm.getelementptr %150[%179] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %177, %180 : i64, !llvm.ptr
      %181 = llvm.load %162 : !llvm.ptr -> i32
      %182 = arith.constant 1 : i32
      %183 = arith.addi %181, %182 : i32
      llvm.store %183, %162 : i32, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    %184 = arith.constant 1 : i32
    %186 = arith.extsi %184 : i32 to i64
    %185 = arith.remsi %186, %arg2 : i64
    %187 = llvm.mlir.constant(1 : i64) : i64
    %188 = llvm.alloca %187 x i64 : (i64) -> !llvm.ptr
    llvm.store %185, %188 : i64, !llvm.ptr
    %189 = arith.constant 0 : i32
    %190 = llvm.mlir.constant(1 : i64) : i64
    %191 = llvm.alloca %190 x i32 : (i64) -> !llvm.ptr
    llvm.store %189, %191 : i32, !llvm.ptr
    cf.br ^bb30
    ^bb30:
    %192 = llvm.load %191 : !llvm.ptr -> i32
    %193 = arith.constant 1 : i32
    %194 = arith.subi %arg1, %193 : i32
    %195 = arith.cmpi slt, %192, %194 : i32
    cf.cond_br %195, ^bb31, ^bb32
    ^bb31:
      %197 = arith.constant 1 : i32
      %198 = arith.subi %arg1, %197 : i32
      %199 = llvm.load %191 : !llvm.ptr -> i32
      %200 = arith.subi %198, %199 : i32
      %201 = arith.extsi %200 : i32 to i64
      %202 = llvm.getelementptr %arg0[%201] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %196 = llvm.load %202 : !llvm.ptr -> i64
      %204 = arith.constant 1 : i32
      %205 = arith.subi %arg1, %204 : i32
      %206 = llvm.load %191 : !llvm.ptr -> i32
      %207 = arith.subi %205, %206 : i32
      %208 = arith.constant 1 : i32
      %209 = arith.subi %207, %208 : i32
      %210 = arith.extsi %209 : i32 to i64
      %211 = llvm.getelementptr %arg0[%210] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %203 = llvm.load %211 : !llvm.ptr -> i64
      %212 = arith.subi %196, %203 : i64
      %213 = arith.constant 1 : i32
      %215 = arith.extsi %213 : i32 to i64
      %214 = arith.subi %212, %215 : i64
      %216 = arith.constant 0 : i32
      %218 = arith.extsi %216 : i32 to i64
      %217 = arith.cmpi sle, %214, %218 : i64
      cf.cond_br %217, ^bb33, ^bb34
      ^bb33:
        %219 = llvm.load %191 : !llvm.ptr -> i32
        %220 = arith.constant 1 : i32
        %221 = arith.addi %219, %220 : i32
        llvm.store %221, %191 : i32, !llvm.ptr
        cf.br ^bb30
      ^bb34:
        cf.br ^bb35
      ^bb35:
      %223 = llvm.load %191 : !llvm.ptr -> i32
      %224 = arith.constant 1 : i32
      %225 = arith.addi %223, %224 : i32
      %226 = arith.extsi %225 : i32 to i64
      %227 = llvm.getelementptr %150[%226] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %222 = llvm.load %227 : !llvm.ptr -> i64
      %228 = llvm.load %188 : !llvm.ptr -> i64
      %229 = func.call @powmod(%222, %214, %arg2) : (i64, i64, i64) -> i64
      %230 = arith.muli %228, %229 : i64
      %231 = arith.remsi %230, %arg2 : i64
      llvm.store %231, %188 : i64, !llvm.ptr
      %232 = llvm.load %191 : !llvm.ptr -> i32
      %233 = arith.constant 1 : i32
      %234 = arith.addi %232, %233 : i32
      llvm.store %234, %191 : i32, !llvm.ptr
      cf.br ^bb30
    ^bb32:
    func.call @free(%150) : (!llvm.ptr) -> ()
    %236 = llvm.load %188 : !llvm.ptr -> i64
    func.return %236 : i64
  }
  func.func @main() -> i32 {
    %237 = arith.constant 99995705032735 : i32
    %238 = arith.extsi %237 : i32 to i64
    %239 = arith.constant 62 : i32
    %240 = arith.constant 4000 : i32
    %242 = arith.extsi %240 : i32 to i64
    %243 = arith.constant 8 : i32
    %244 = arith.extsi %243 : i32 to i64
    %241 = func.call @calloc(%242, %244) : (i64, i64) -> !llvm.ptr
    %245 = func.call @one_positions_via_binom(%238, %239, %241) : (i64, i32, !llvm.ptr) -> i32
    %247 = llvm.mlir.addressof @MOD : !llvm.ptr
    %248 = llvm.load %247 : !llvm.ptr -> i64
    %246 = func.call @A_from_positions(%241, %245, %248) : (!llvm.ptr, i32, i64) -> i64
    func.call @free(%241) : (!llvm.ptr) -> ()
    %250 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %251 = llvm.call @printf(%250, %246) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %252 = arith.constant 0 : i32
    func.return %252 : i32
  }
}