Problem 813

XOR-Powers — degrees of (1+x+x^3)^exp over GF(2); sum 2^d mod 1e9+7. exp = 8^12 * 12^8 = 2^52 * 6561; work in i128 for degree values.

Answer14063639
Output14063639
StatusPASS
Native helperno
Runtime0 ms
Peak memory1104 KB
Time complexityO(n^2) (estimated)
Space complexityO(n) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)O(n * k)
Space complexityO(n)O(n)
ApproachFlow solutionKey search and XOR decryption
VerdictUnknown

Flow source

# Project Euler 813
# XOR-Powers — degrees of (1+x+x^3)^exp over GF(2); sum 2^d mod 1e9+7.
# exp = 8^12 * 12^8 = 2^52 * 6561; work in i128 for degree values.

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) != 0 {
            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
}

function toggle(degs: ptr<i128>, n: ptr<i64>, val: i128) -> void {
    let mut lo: i64 = 0
    let mut hi: i64 = n[0]
    while lo < hi {
        let mid: i64 = (lo + hi) / 2
        if degs[mid] < val {
            lo = mid + 1
        } else {
            hi = mid
        }
    }
    if lo < n[0] && degs[lo] == val {
        let mut i: i64 = lo
        while i + 1 < n[0] {
            degs[i] = degs[i + 1]
            i = i + 1
        }
        n[0] = n[0] - 1
    } else {
        let mut i: i64 = n[0]
        while i > lo {
            degs[i] = degs[i - 1]
            i = i - 1
        }
        degs[lo] = val
        n[0] = n[0] + 1
    }
}

function solve() -> i64 {
    # Bit values of exp = 6561 << 52
    let bits: ptr<i128> = calloc(16, 16)
    let mut bcount: i64 = 0
    let mut coeff: i64 = 6561
    let mut k: i64 = 0
    while coeff > 0 {
        if (coeff & 1) != 0 {
            # 2^(52+k) as i128
            let mut p: i128 = 1
            let mut e: i64 = 0
            while e < 52 + k {
                p = p << 1
                e = e + 1
            }
            bits[bcount] = p
            bcount = bcount + 1
        }
        coeff = coeff >> 1
        k = k + 1
    }

    let mut cap: i64 = 1
    let mut i: i64 = 0
    while i < bcount {
        cap = cap * 3
        i = i + 1
    }
    let degs: ptr<i128> = calloc(cap + 8, 16)
    let mut n: i64 = 1
    degs[0] = 0
    i = 0
    while i < bcount {
        let bv: i128 = bits[i]
        let newd: ptr<i128> = calloc(cap + 8, 16)
        let mut nn: i64 = 0
        let mut j: i64 = 0
        while j < n {
            let d0: i128 = degs[j]
            toggle(newd, &nn, d0)
            toggle(newd, &nn, d0 + bv)
            toggle(newd, &nn, d0 + 3 * bv)
            j = j + 1
        }
        j = 0
        while j < nn {
            degs[j] = newd[j]
            j = j + 1
        }
        n = nn
        free(newd)
        i = i + 1
    }

    let mut ans: i64 = 0
    i = 0
    while i < n {
        # 2^d mod MOD; reduce d mod (MOD-1)
        let dmod: i64 = (degs[i] % ((MOD - 1) as i128)) as i64
        if dmod < 0 {
            # shouldn't happen for nonnegative degrees
        }
        ans = (ans + modpow(2, dmod, MOD)) % MOD
        i = i + 1
    }
    free(bits)
    free(degs)
    return ans
}

function main() -> i32 {
    printf("%lld\n", solve())
    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);
void toggle_ptr_i128_ptr_i64_i128(__int128* degs, int64_t* n, __int128 val);
int64_t solve(void);
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) != 0) {
            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;
}

void toggle_ptr_i128_ptr_i64_i128(__int128* degs, int64_t* n, __int128 val) {
    int64_t lo = 0;
    int64_t hi = n[0];
    while (lo < hi) {
        int64_t mid = FLOW_CHECKED_DIV(((lo + hi)), (2));
        if (degs[mid] < val) {
            lo = (mid + 1);
        } else {
            hi = mid;
        }
    }
    if ((lo < n[0] && degs[lo] == val)) {
        int64_t i = lo;
        while ((i + 1) < n[0]) {
            degs[i] = degs[(i + 1)];
            i = (i + 1);
        }
        n[0] = (n[0] - 1);
    } else {
        int64_t i = n[0];
        while (i > lo) {
            degs[i] = degs[(i - 1)];
            i = (i - 1);
        }
        degs[lo] = val;
        n[0] = (n[0] + 1);
    }
}

int64_t solve(void) {
    __int128* bits = (__int128*)(calloc(16, 16));
    int64_t bcount = 0;
    int64_t coeff = 6561;
    int64_t k = 0;
    while (coeff > 0) {
        if ((coeff & 1) != 0) {
            __int128 p = 1;
            int64_t e = 0;
            while (e < (52 + k)) {
                p = FLOW_CHECKED_SHL((p), (1));
                e = (e + 1);
            }
            bits[bcount] = p;
            bcount = (bcount + 1);
        }
        coeff = FLOW_CHECKED_SHR((coeff), (1));
        k = (k + 1);
    }
    int64_t cap = 1;
    int64_t i = 0;
    while (i < bcount) {
        cap = (cap * 3);
        i = (i + 1);
    }
    __int128* degs = (__int128*)(calloc((cap + 8), 16));
    int64_t n = 1;
    degs[0] = 0;
    i = 0;
    while (i < bcount) {
        __int128 bv = bits[i];
        __int128* newd = (__int128*)(calloc((cap + 8), 16));
        int64_t nn = 0;
        int64_t j = 0;
        while (j < n) {
            __int128 d0 = degs[j];
            toggle_ptr_i128_ptr_i64_i128(newd, (&(nn)), d0);
            toggle_ptr_i128_ptr_i64_i128(newd, (&(nn)), (d0 + bv));
            toggle_ptr_i128_ptr_i64_i128(newd, (&(nn)), (d0 + (3 * bv)));
            j = (j + 1);
        }
        j = 0;
        while (j < nn) {
            degs[j] = newd[j];
            j = (j + 1);
        }
        n = nn;
        free(newd);
        i = (i + 1);
    }
    int64_t ans = 0;
    i = 0;
    while (i < n) {
        int64_t dmod = ((int64_t)(FLOW_CHECKED_MOD((degs[i]), (((__int128)((MOD - 1)))))));
        if (dmod < 0) {
        }
        ans = FLOW_CHECKED_MOD(((ans + modpow_i64_i64_i64(2, dmod, MOD))), (MOD));
        i = (i + 1);
    }
    free(bits);
    free(degs);
    return ans;
}

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