Problem 789

Minimal cost pairing of 1..p-1 mod p = 2000000011: pair costs are (a*b) mod p; among all pairings of minimal total cost, print the product of the pair costs (exact integer). Theory. By Wilson, the product of the pair costs of any pairing is congruent to -1 (mod p). Costs are at least 1, and replacing a composite cost c = u*v by pairs of costs u and v never raises the total since (u-1)+(v-1) <= uv-1. So the total is at least (p-1)/2 + W, where W is the minimal weight sum e_q*(q-1) over prime multisets q^e_q whose product is -1 mod p. Conversely any such prime multiset q_1..q_r is realised by the chain pairing (1, Q_1), (Q_1^-1, Q_2), ..., (Q_{r-1}^-1, Q_r = p-1) with Q_i = q_1*...*q_i mod p, all other elements paired with their inverses at cost 1. Hence optimal cost multisets are exactly the minimal-weight prime factorisations of integers N == -1 (mod p); for p = 2000000011 the minimiser is unique (verified by the exhaustive search below), so the cost product is that N. Search. Every multiset splits as X * 2^a * 3^b with X over primes >= 5. Hash all residues 2^a 3^b (a + 2b <= 239) to their minimal weight, then DFS over X keeping the running inverse residue and weight; each node looks up -X^-1 in the table. Weight cap 239 is an upper bound reached by the search itself, so the minimum is exact. The unique minimiser N fits in i128 and is printed by repeated division by 10.

Answer13431419535872807040
Output13431419535872807040
StatusPASS
Native helperno
Runtime340 ms
Peak memory2192 KB
Time complexityO(n log n) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n log n)O(sqrt(n))
Space complexityO(n^2)O(1)
ApproachFlow solutionTrial division or Pollard rho
VerdictSuboptimal

Flow source

# Project Euler 789
# Minimal cost pairing of 1..p-1 mod p = 2000000011: pair costs are
# (a*b) mod p; among all pairings of minimal total cost, print the
# product of the pair costs (exact integer).
#
# Theory. By Wilson, the product of the pair costs of any pairing is
# congruent to -1 (mod p). Costs are at least 1, and replacing a
# composite cost c = u*v by pairs of costs u and v never raises the
# total since (u-1)+(v-1) <= uv-1. So the total is at least
# (p-1)/2 + W, where W is the minimal weight sum e_q*(q-1) over prime
# multisets q^e_q whose product is -1 mod p. Conversely any such prime
# multiset q_1..q_r is realised by the chain pairing (1, Q_1),
# (Q_1^-1, Q_2), ..., (Q_{r-1}^-1, Q_r = p-1) with Q_i = q_1*...*q_i
# mod p, all other elements paired with their inverses at cost 1.
# Hence optimal cost multisets are exactly the minimal-weight prime
# factorisations of integers N == -1 (mod p); for p = 2000000011 the
# minimiser is unique (verified by the exhaustive search below), so
# the cost product is that N.
#
# Search. Every multiset splits as X * 2^a * 3^b with X over primes
# >= 5. Hash all residues 2^a 3^b (a + 2b <= 239) to their minimal
# weight, then DFS over X keeping the running inverse residue and
# weight; each node looks up -X^-1 in the table. Weight cap 239 is an
# upper bound reached by the search itself, so the minimum is exact.
# The unique minimiser N fits in i128 and is printed by repeated
# division by 10.

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

const P: i64 = 2000000011
const CAP: i64 = 239
const HB: i64 = 65536
const HMASK: i64 = 65535
const QMAX: i64 = 241

function mulmod(a: i64, b: i64) -> i64 {
    # a, b < P < 2^31, so a*b < 2^62 fits i64
    return (a * b) % P
}

function modpow(b: i64, e: i64) -> i64 {
    let mut r: i64 = 1
    let mut bb: i64 = b % P
    let mut ee: i64 = e
    while ee > 0 {
        if ee % 2 == 1 {
            r = mulmod(r, bb)
        }
        bb = mulmod(bb, bb)
        ee = ee / 2
    }
    return r
}

function hslot(tk: ptr<i64>, t: i64) -> i64 {
    let mut h: i64 = ((t >> 15) ^ t) & HMASK
    while tk[h] != 0 && tk[h] != t {
        h = (h + 1) & HMASK
    }
    return h
}

# DFS over multisets of primes >= 5 (Q ascending, weights Q[j]-1).
# ri = inverse of the running product, w = weight so far, d = depth.
# st: 0 best, 1 ties, 2 saved w, 3 saved target residue, 4 saved depth.
function dfs(i: i64, ri: i64, w: i64, d: i64,
             Q: ptr<i64>, QI: ptr<i64>, nq: i64,
             tk: ptr<i64>, tw: ptr<i64>,
             st: ptr<i64>, stk: ptr<i64>, sol: ptr<i64>) -> i64 {
    # target: 2^a 3^b == -1 / X  (mod P)
    let t: i64 = ((P - 1) * ri) % P
    let h: i64 = hslot(tk, t)
    if tk[h] == t {
        let cand: i64 = w + tw[h]
        if cand < st[0] {
            st[0] = cand
            st[1] = 1
            st[2] = w
            st[3] = t
            st[4] = d
            let mut k: i64 = 0
            while k < d {
                sol[k] = stk[k]
                k = k + 1
            }
        } else {
            if cand == st[0] {
                st[1] = st[1] + 1
            }
        }
    }
    let mut j: i64 = i
    while j < nq {
        let wj: i64 = Q[j] - 1
        if w + wj > st[0] {
            j = nq
        } else {
            stk[d] = Q[j]
            dfs(j, mulmod(ri, QI[j]), w + wj, d + 1,
                Q, QI, nq, tk, tw, st, stk, sol)
            j = j + 1
        }
    }
    return 0
}

function main() -> i32 {
    # sieve primes up to QMAX
    let comp: ptr<i64> = calloc(QMAX + 1, 8)
    let mut i: i64 = 2
    while i * i <= QMAX {
        if comp[i] == 0 {
            let mut j: i64 = i * i
            while j <= QMAX {
                comp[j] = 1
                j = j + i
            }
        }
        i = i + 1
    }
    let Q: ptr<i64> = calloc(64, 8)
    let QI: ptr<i64> = calloc(64, 8)
    let mut nq: i64 = 0
    i = 5
    while i <= QMAX {
        if comp[i] == 0 && i - 1 <= CAP && i < P {
            Q[nq] = i
            QI[nq] = modpow(i, P - 2)
            nq = nq + 1
        }
        i = i + 1
    }

    # hash residues of 2^a 3^b (a + 2b <= CAP) to minimal weight a + 2b
    let tk: ptr<i64> = calloc(HB, 8)
    let tw: ptr<i64> = calloc(HB, 8)
    let mut b: i64 = 0
    let mut r3: i64 = 1
    while 2 * b <= CAP {
        let mut cur: i64 = r3
        let mut a: i64 = 0
        while a + 2 * b <= CAP {
            let h: i64 = hslot(tk, cur)
            if tk[h] == 0 {
                tk[h] = cur
                tw[h] = a + 2 * b
            } else {
                if a + 2 * b < tw[h] {
                    tw[h] = a + 2 * b
                }
            }
            cur = mulmod(cur, 2)
            a = a + 1
        }
        r3 = mulmod(r3, 3)
        b = b + 1
    }

    # exhaustive search up to weight CAP
    let st: ptr<i64> = calloc(8, 8)
    let stk: ptr<i64> = calloc(64, 8)
    let sol: ptr<i64> = calloc(64, 8)
    st[0] = CAP + 1
    dfs(0, 1, 0, 0, Q, QI, nq, tk, tw, st, stk, sol)

    # reconstruct N = (solution primes >= 5) * 2^a 3^b
    let mut N: i128 = 1 as i128
    let mut k: i64 = 0
    while k < st[4] {
        N = N * (sol[k] as i128)
        k = k + 1
    }
    let rem: i64 = st[0] - st[2]
    let tt: i64 = st[3]
    let mut ba: i64 = -1
    let mut bb2: i64 = -1
    b = 0
    r3 = 1
    while 2 * b <= rem {
        let mut cur: i64 = r3
        let mut a: i64 = 0
        while a + 2 * b <= rem {
            if cur == tt && a + 2 * b == rem {
                ba = a
                bb2 = b
            }
            cur = mulmod(cur, 2)
            a = a + 1
        }
        r3 = mulmod(r3, 3)
        b = b + 1
    }
    k = 0
    while k < ba {
        N = N * (2 as i128)
        k = k + 1
    }
    k = 0
    while k < bb2 {
        N = N * (3 as i128)
        k = k + 1
    }

    # print N in decimal (exceeds signed 64-bit)
    let digs: ptr<i64> = calloc(64, 8)
    let mut nd: i64 = 0
    let mut x: i128 = N
    while x > (0 as i128) {
        digs[nd] = (x % (10 as i128)) as i64
        x = x / (10 as i128)
        nd = nd + 1
    }
    let mut j2: i64 = nd - 1
    while j2 >= 0 {
        printf("%c", (48 + digs[j2]) as i32)
        j2 = j2 - 1
    }
    printf("\n")

    free(comp)
    free(Q)
    free(QI)
    free(tk)
    free(tw)
    free(st)
    free(stk)
    free(sol)
    free(digs)
    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 mulmod_i64_i64(int64_t a, int64_t b);
int64_t modpow_i64_i64(int64_t b, int64_t e);
int64_t hslot_ptr_i64_i64(int64_t* tk, int64_t t);
int64_t dfs_i64_i64_i64_i64_ptr_i64_ptr_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t i, int64_t ri, int64_t w, int64_t d, int64_t* Q, int64_t* QI, int64_t nq, int64_t* tk, int64_t* tw, int64_t* st, int64_t* stk, int64_t* sol);
int32_t main(void);

static const int64_t P = 2000000011;
static const int64_t CAP = 239;
static const int64_t HB = 65536;
static const int64_t HMASK = 65535;
static const int64_t QMAX = 241;



int64_t mulmod_i64_i64(int64_t a, int64_t b) {
    return FLOW_CHECKED_MOD(((a * b)), (P));
}

int64_t modpow_i64_i64(int64_t b, int64_t e) {
    int64_t r = 1;
    int64_t bb = FLOW_CHECKED_MOD((b), (P));
    int64_t ee = e;
    while (ee > 0) {
        if (FLOW_CHECKED_MOD((ee), (2)) == 1) {
            r = mulmod_i64_i64(r, bb);
        }
        bb = mulmod_i64_i64(bb, bb);
        ee = FLOW_CHECKED_DIV((ee), (2));
    }
    return r;
}

int64_t hslot_ptr_i64_i64(int64_t* tk, int64_t t) {
    int64_t h = ((FLOW_CHECKED_SHR((t), (15)) ^ t) & HMASK);
    while ((tk[h] != 0 && tk[h] != t)) {
        h = ((h + 1) & HMASK);
    }
    return h;
}

int64_t dfs_i64_i64_i64_i64_ptr_i64_ptr_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(int64_t i, int64_t ri, int64_t w, int64_t d, int64_t* Q, int64_t* QI, int64_t nq, int64_t* tk, int64_t* tw, int64_t* st, int64_t* stk, int64_t* sol) {
    int64_t t = FLOW_CHECKED_MOD((((P - 1) * ri)), (P));
    int64_t h = hslot_ptr_i64_i64(tk, t);
    if (tk[h] == t) {
        int64_t cand = (w + tw[h]);
        if (cand < st[0]) {
            st[0] = cand;
            st[1] = 1;
            st[2] = w;
            st[3] = t;
            st[4] = d;
            int64_t k = 0;
            while (k < d) {
                sol[k] = stk[k];
                k = (k + 1);
            }
        } else {
            if (cand == st[0]) {
                st[1] = (st[1] + 1);
            }
        }
    }
    int64_t j = i;
    while (j < nq) {
        int64_t wj = (Q[j] - 1);
        if ((w + wj) > st[0]) {
            j = nq;
        } else {
            stk[d] = Q[j];
            dfs_i64_i64_i64_i64_ptr_i64_ptr_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(j, mulmod_i64_i64(ri, QI[j]), (w + wj), (d + 1), Q, QI, nq, tk, tw, st, stk, sol);
            j = (j + 1);
        }
    }
    return 0;
}

int32_t main(void) {
    int64_t* comp = (int64_t*)(calloc((QMAX + 1), 8));
    int64_t i = 2;
    while ((i * i) <= QMAX) {
        if (comp[i] == 0) {
            int64_t j = (i * i);
            while (j <= QMAX) {
                comp[j] = 1;
                j = (j + i);
            }
        }
        i = (i + 1);
    }
    int64_t* Q = (int64_t*)(calloc(64, 8));
    int64_t* QI = (int64_t*)(calloc(64, 8));
    int64_t nq = 0;
    i = 5;
    while (i <= QMAX) {
        if (((comp[i] == 0 && (i - 1) <= CAP) && i < P)) {
            Q[nq] = i;
            QI[nq] = modpow_i64_i64(i, (P - 2));
            nq = (nq + 1);
        }
        i = (i + 1);
    }
    int64_t* tk = (int64_t*)(calloc(HB, 8));
    int64_t* tw = (int64_t*)(calloc(HB, 8));
    int64_t b = 0;
    int64_t r3 = 1;
    while ((2 * b) <= CAP) {
        int64_t cur = r3;
        int64_t a = 0;
        while ((a + (2 * b)) <= CAP) {
            int64_t h = hslot_ptr_i64_i64(tk, cur);
            if (tk[h] == 0) {
                tk[h] = cur;
                tw[h] = (a + (2 * b));
            } else {
                if ((a + (2 * b)) < tw[h]) {
                    tw[h] = (a + (2 * b));
                }
            }
            cur = mulmod_i64_i64(cur, 2);
            a = (a + 1);
        }
        r3 = mulmod_i64_i64(r3, 3);
        b = (b + 1);
    }
    int64_t* st = (int64_t*)(calloc(8, 8));
    int64_t* stk = (int64_t*)(calloc(64, 8));
    int64_t* sol = (int64_t*)(calloc(64, 8));
    st[0] = (CAP + 1);
    dfs_i64_i64_i64_i64_ptr_i64_ptr_i64_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64_ptr_i64(0, 1, 0, 0, Q, QI, nq, tk, tw, st, stk, sol);
    __int128 N = ((__int128)(1));
    int64_t k = 0;
    while (k < st[4]) {
        N = (N * ((__int128)(sol[k])));
        k = (k + 1);
    }
    int64_t rem = (st[0] - st[2]);
    int64_t tt = st[3];
    int64_t ba = (-1);
    int64_t bb2 = (-1);
    b = 0;
    r3 = 1;
    while ((2 * b) <= rem) {
        int64_t cur = r3;
        int64_t a = 0;
        while ((a + (2 * b)) <= rem) {
            if ((cur == tt && (a + (2 * b)) == rem)) {
                ba = a;
                bb2 = b;
            }
            cur = mulmod_i64_i64(cur, 2);
            a = (a + 1);
        }
        r3 = mulmod_i64_i64(r3, 3);
        b = (b + 1);
    }
    k = 0;
    while (k < ba) {
        N = (N * ((__int128)(2)));
        k = (k + 1);
    }
    k = 0;
    while (k < bb2) {
        N = (N * ((__int128)(3)));
        k = (k + 1);
    }
    int64_t* digs = (int64_t*)(calloc(64, 8));
    int64_t nd = 0;
    __int128 x = N;
    while (x > ((__int128)(0))) {
        digs[nd] = ((int64_t)(FLOW_CHECKED_MOD((x), (((__int128)(10))))));
        x = FLOW_CHECKED_DIV((x), (((__int128)(10))));
        nd = (nd + 1);
    }
    int64_t j2 = (nd - 1);
    while (j2 >= 0) {
        printf("%c", ((int32_t)((48 + digs[j2]))));
        j2 = (j2 - 1);
    }
    printf("\n");
    free(comp);
    free(Q);
    free(QI);
    free(tk);
    free(tw);
    free(st);
    free(stk);
    free(sol);
    free(digs);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%c\00") {addr_space = 0 : i32} : !llvm.array<3 x i8>
  llvm.mlir.global internal constant @str_1("\n\00") {addr_space = 0 : i32} : !llvm.array<2 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  // Constant: P
  llvm.mlir.global internal constant @P(2000000011 : i64) : i64
  // Constant: CAP
  llvm.mlir.global internal constant @CAP(239 : i64) : i64
  // Constant: HB
  llvm.mlir.global internal constant @HB(65536 : i64) : i64
  // Constant: HMASK
  llvm.mlir.global internal constant @HMASK(65535 : i64) : i64
  // Constant: QMAX
  llvm.mlir.global internal constant @QMAX(241 : i64) : i64
  func.func @mulmod(%arg0: i64, %arg1: i64) -> i64 {
    %0 = arith.muli %arg0, %arg1 : i64
    %1 = llvm.mlir.addressof @P : !llvm.ptr
    %2 = llvm.load %1 : !llvm.ptr -> i64
    %3 = arith.remsi %0, %2 : i64
    func.return %3 : i64
  }
  func.func @modpow(%arg0: i64, %arg1: i64) -> i64 {
    %4 = arith.constant 1 : i32
    %5 = arith.extsi %4 : i32 to i64
    %6 = llvm.mlir.constant(1 : i64) : i64
    %7 = llvm.alloca %6 x i64 : (i64) -> !llvm.ptr
    llvm.store %5, %7 : i64, !llvm.ptr
    %8 = llvm.mlir.addressof @P : !llvm.ptr
    %9 = llvm.load %8 : !llvm.ptr -> i64
    %10 = arith.remsi %arg0, %9 : i64
    %11 = llvm.mlir.constant(1 : i64) : i64
    %12 = llvm.alloca %11 x i64 : (i64) -> !llvm.ptr
    llvm.store %10, %12 : i64, !llvm.ptr
    %13 = llvm.mlir.constant(1 : i64) : i64
    %14 = llvm.alloca %13 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg1, %14 : i64, !llvm.ptr
    cf.br ^bb0
    ^bb0:
    %15 = llvm.load %14 : !llvm.ptr -> i64
    %16 = arith.constant 0 : i32
    %18 = arith.extsi %16 : i32 to i64
    %17 = arith.cmpi sgt, %15, %18 : i64
    cf.cond_br %17, ^bb1, ^bb2
    ^bb1:
      %19 = llvm.load %14 : !llvm.ptr -> i64
      %20 = arith.constant 2 : i32
      %22 = arith.extsi %20 : i32 to i64
      %21 = arith.remsi %19, %22 : i64
      %23 = arith.constant 1 : i32
      %25 = arith.extsi %23 : i32 to i64
      %24 = arith.cmpi eq, %21, %25 : i64
      cf.cond_br %24, ^bb3, ^bb4
      ^bb3:
        %27 = llvm.load %7 : !llvm.ptr -> i64
        %28 = llvm.load %12 : !llvm.ptr -> i64
        %26 = func.call @mulmod(%27, %28) : (i64, i64) -> i64
        llvm.store %26, %7 : i64, !llvm.ptr
        cf.br ^bb5
      ^bb4:
        cf.br ^bb5
      ^bb5:
      %30 = llvm.load %12 : !llvm.ptr -> i64
      %31 = llvm.load %12 : !llvm.ptr -> i64
      %29 = func.call @mulmod(%30, %31) : (i64, i64) -> i64
      llvm.store %29, %12 : i64, !llvm.ptr
      %32 = llvm.load %14 : !llvm.ptr -> i64
      %33 = arith.constant 2 : i32
      %35 = arith.extsi %33 : i32 to i64
      %34 = arith.divsi %32, %35 : i64
      llvm.store %34, %14 : i64, !llvm.ptr
      cf.br ^bb0
    ^bb2:
    %36 = llvm.load %7 : !llvm.ptr -> i64
    func.return %36 : i64
  }
  func.func @hslot(%arg0: !llvm.ptr, %arg1: i64) -> i64 {
    %37 = arith.constant 15 : i32
    %39 = arith.extsi %37 : i32 to i64
    %38 = arith.shrsi %arg1, %39 : i64
    %40 = arith.xori %38, %arg1 : i64
    %41 = llvm.mlir.addressof @HMASK : !llvm.ptr
    %42 = llvm.load %41 : !llvm.ptr -> i64
    %43 = arith.andi %40, %42 : i64
    %44 = llvm.mlir.constant(1 : i64) : i64
    %45 = llvm.alloca %44 x i64 : (i64) -> !llvm.ptr
    llvm.store %43, %45 : i64, !llvm.ptr
    cf.br ^bb6
    ^bb6:
    %47 = llvm.load %45 : !llvm.ptr -> i64
    %48 = llvm.getelementptr %arg0[%47] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %46 = llvm.load %48 : !llvm.ptr -> i64
    %49 = arith.constant 0 : i32
    %51 = arith.extsi %49 : i32 to i64
    %50 = arith.cmpi ne, %46, %51 : i64
    %52 = scf.if %50 -> (i1) {
      %54 = llvm.load %45 : !llvm.ptr -> i64
      %55 = llvm.getelementptr %arg0[%54] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %53 = llvm.load %55 : !llvm.ptr -> i64
      %56 = arith.cmpi ne, %53, %arg1 : i64
      scf.yield %56 : i1
    } else {
      %57 = arith.constant false
      scf.yield %57 : i1
    }
    cf.cond_br %52, ^bb7, ^bb8
    ^bb7:
      %58 = llvm.load %45 : !llvm.ptr -> i64
      %59 = arith.constant 1 : i32
      %61 = arith.extsi %59 : i32 to i64
      %60 = arith.addi %58, %61 : i64
      %62 = llvm.mlir.addressof @HMASK : !llvm.ptr
      %63 = llvm.load %62 : !llvm.ptr -> i64
      %64 = arith.andi %60, %63 : i64
      llvm.store %64, %45 : i64, !llvm.ptr
      cf.br ^bb6
    ^bb8:
    %65 = llvm.load %45 : !llvm.ptr -> i64
    func.return %65 : i64
  }
  func.func @dfs(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i64, %arg4: !llvm.ptr, %arg5: !llvm.ptr, %arg6: i64, %arg7: !llvm.ptr, %arg8: !llvm.ptr, %arg9: !llvm.ptr, %arg10: !llvm.ptr, %arg11: !llvm.ptr) -> i64 {
    %66 = llvm.mlir.addressof @P : !llvm.ptr
    %67 = llvm.load %66 : !llvm.ptr -> i64
    %68 = arith.constant 1 : i32
    %70 = arith.extsi %68 : i32 to i64
    %69 = arith.subi %67, %70 : i64
    %71 = arith.muli %69, %arg1 : i64
    %72 = llvm.mlir.addressof @P : !llvm.ptr
    %73 = llvm.load %72 : !llvm.ptr -> i64
    %74 = arith.remsi %71, %73 : i64
    %75 = func.call @hslot(%arg7, %74) : (!llvm.ptr, i64) -> i64
    %77 = llvm.getelementptr %arg7[%75] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %76 = llvm.load %77 : !llvm.ptr -> i64
    %78 = arith.cmpi eq, %76, %74 : i64
    cf.cond_br %78, ^bb9, ^bb10
    ^bb9:
      %80 = llvm.getelementptr %arg8[%75] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %79 = llvm.load %80 : !llvm.ptr -> i64
      %81 = arith.addi %arg2, %79 : i64
      %83 = arith.constant 0 : i32
      %84 = arith.extsi %83 : i32 to i64
      %85 = llvm.getelementptr %arg9[%84] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %82 = llvm.load %85 : !llvm.ptr -> i64
      %86 = arith.cmpi slt, %81, %82 : i64
      cf.cond_br %86, ^bb12, ^bb13
      ^bb12:
        %87 = arith.constant 0 : i32
        %88 = arith.extsi %87 : i32 to i64
        %89 = llvm.getelementptr %arg9[%88] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %81, %89 : i64, !llvm.ptr
        %90 = arith.constant 1 : i32
        %91 = arith.constant 1 : i32
        %92 = arith.extsi %90 : i32 to i64
        %93 = arith.extsi %91 : i32 to i64
        %94 = llvm.getelementptr %arg9[%93] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %92, %94 : i64, !llvm.ptr
        %95 = arith.constant 2 : i32
        %96 = arith.extsi %95 : i32 to i64
        %97 = llvm.getelementptr %arg9[%96] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %arg2, %97 : i64, !llvm.ptr
        %98 = arith.constant 3 : i32
        %99 = arith.extsi %98 : i32 to i64
        %100 = llvm.getelementptr %arg9[%99] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %74, %100 : i64, !llvm.ptr
        %101 = arith.constant 4 : i32
        %102 = arith.extsi %101 : i32 to i64
        %103 = llvm.getelementptr %arg9[%102] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %arg3, %103 : i64, !llvm.ptr
        %104 = arith.constant 0 : i32
        %105 = arith.extsi %104 : i32 to i64
        %106 = llvm.mlir.constant(1 : i64) : i64
        %107 = llvm.alloca %106 x i64 : (i64) -> !llvm.ptr
        llvm.store %105, %107 : i64, !llvm.ptr
        cf.br ^bb15
        ^bb15:
        %108 = llvm.load %107 : !llvm.ptr -> i64
        %109 = arith.cmpi slt, %108, %arg3 : i64
        cf.cond_br %109, ^bb16, ^bb17
        ^bb16:
          %111 = llvm.load %107 : !llvm.ptr -> i64
          %112 = llvm.getelementptr %arg10[%111] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %110 = llvm.load %112 : !llvm.ptr -> i64
          %113 = llvm.load %107 : !llvm.ptr -> i64
          %114 = llvm.getelementptr %arg11[%113] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %110, %114 : i64, !llvm.ptr
          %115 = llvm.load %107 : !llvm.ptr -> i64
          %116 = arith.constant 1 : i32
          %118 = arith.extsi %116 : i32 to i64
          %117 = arith.addi %115, %118 : i64
          llvm.store %117, %107 : i64, !llvm.ptr
          cf.br ^bb15
        ^bb17:
        cf.br ^bb14
      ^bb13:
        %120 = arith.constant 0 : i32
        %121 = arith.extsi %120 : i32 to i64
        %122 = llvm.getelementptr %arg9[%121] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %119 = llvm.load %122 : !llvm.ptr -> i64
        %123 = arith.cmpi eq, %81, %119 : i64
        cf.cond_br %123, ^bb18, ^bb19
        ^bb18:
          %125 = arith.constant 1 : i32
          %126 = arith.extsi %125 : i32 to i64
          %127 = llvm.getelementptr %arg9[%126] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %124 = llvm.load %127 : !llvm.ptr -> i64
          %128 = arith.constant 1 : i32
          %130 = arith.extsi %128 : i32 to i64
          %129 = arith.addi %124, %130 : i64
          %131 = arith.constant 1 : i32
          %132 = arith.extsi %131 : i32 to i64
          %133 = llvm.getelementptr %arg9[%132] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %129, %133 : i64, !llvm.ptr
          cf.br ^bb20
        ^bb19:
          cf.br ^bb20
        ^bb20:
        cf.br ^bb14
      ^bb14:
      cf.br ^bb11
    ^bb10:
      cf.br ^bb11
    ^bb11:
    %134 = llvm.mlir.constant(1 : i64) : i64
    %135 = llvm.alloca %134 x i64 : (i64) -> !llvm.ptr
    llvm.store %arg0, %135 : i64, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %136 = llvm.load %135 : !llvm.ptr -> i64
    %137 = arith.cmpi slt, %136, %arg6 : i64
    cf.cond_br %137, ^bb22, ^bb23
    ^bb22:
      %139 = llvm.load %135 : !llvm.ptr -> i64
      %140 = llvm.getelementptr %arg4[%139] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %138 = llvm.load %140 : !llvm.ptr -> i64
      %141 = arith.constant 1 : i32
      %143 = arith.extsi %141 : i32 to i64
      %142 = arith.subi %138, %143 : i64
      %144 = arith.addi %arg2, %142 : i64
      %146 = arith.constant 0 : i32
      %147 = arith.extsi %146 : i32 to i64
      %148 = llvm.getelementptr %arg9[%147] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %145 = llvm.load %148 : !llvm.ptr -> i64
      %149 = arith.cmpi sgt, %144, %145 : i64
      cf.cond_br %149, ^bb24, ^bb25
      ^bb24:
        llvm.store %arg6, %135 : i64, !llvm.ptr
        cf.br ^bb26
      ^bb25:
        %151 = llvm.load %135 : !llvm.ptr -> i64
        %152 = llvm.getelementptr %arg4[%151] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %150 = llvm.load %152 : !llvm.ptr -> i64
        %153 = llvm.getelementptr %arg10[%arg3] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %150, %153 : i64, !llvm.ptr
        %155 = llvm.load %135 : !llvm.ptr -> i64
        %158 = llvm.load %135 : !llvm.ptr -> i64
        %159 = llvm.getelementptr %arg5[%158] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %157 = llvm.load %159 : !llvm.ptr -> i64
        %156 = func.call @mulmod(%arg1, %157) : (i64, i64) -> i64
        %160 = arith.addi %arg2, %142 : i64
        %161 = arith.constant 1 : i32
        %163 = arith.extsi %161 : i32 to i64
        %162 = arith.addi %arg3, %163 : i64
        %154 = func.call @dfs(%155, %156, %160, %162, %arg4, %arg5, %arg6, %arg7, %arg8, %arg9, %arg10, %arg11) : (i64, i64, i64, i64, !llvm.ptr, !llvm.ptr, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
        %164 = llvm.load %135 : !llvm.ptr -> i64
        %165 = arith.constant 1 : i32
        %167 = arith.extsi %165 : i32 to i64
        %166 = arith.addi %164, %167 : i64
        llvm.store %166, %135 : i64, !llvm.ptr
        cf.br ^bb26
      ^bb26:
      cf.br ^bb21
    ^bb23:
    %168 = arith.constant 0 : i32
    %169 = arith.extsi %168 : i32 to i64
    func.return %169 : i64
  }
  func.func @main() -> i32 {
    %171 = llvm.mlir.addressof @QMAX : !llvm.ptr
    %172 = llvm.load %171 : !llvm.ptr -> i64
    %173 = arith.constant 1 : i32
    %175 = arith.extsi %173 : i32 to i64
    %174 = arith.addi %172, %175 : i64
    %176 = arith.constant 8 : i32
    %177 = arith.extsi %176 : i32 to i64
    %170 = func.call @calloc(%174, %177) : (i64, i64) -> !llvm.ptr
    %178 = arith.constant 2 : i32
    %179 = arith.extsi %178 : i32 to i64
    %180 = llvm.mlir.constant(1 : i64) : i64
    %181 = llvm.alloca %180 x i64 : (i64) -> !llvm.ptr
    llvm.store %179, %181 : i64, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %182 = llvm.load %181 : !llvm.ptr -> i64
    %183 = llvm.load %181 : !llvm.ptr -> i64
    %184 = arith.muli %182, %183 : i64
    %185 = llvm.mlir.addressof @QMAX : !llvm.ptr
    %186 = llvm.load %185 : !llvm.ptr -> i64
    %187 = arith.cmpi sle, %184, %186 : i64
    cf.cond_br %187, ^bb28, ^bb29
    ^bb28:
      %189 = llvm.load %181 : !llvm.ptr -> i64
      %190 = llvm.getelementptr %170[%189] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %188 = llvm.load %190 : !llvm.ptr -> i64
      %191 = arith.constant 0 : i32
      %193 = arith.extsi %191 : i32 to i64
      %192 = arith.cmpi eq, %188, %193 : i64
      cf.cond_br %192, ^bb30, ^bb31
      ^bb30:
        %194 = llvm.load %181 : !llvm.ptr -> i64
        %195 = llvm.load %181 : !llvm.ptr -> i64
        %196 = arith.muli %194, %195 : i64
        %197 = llvm.mlir.constant(1 : i64) : i64
        %198 = llvm.alloca %197 x i64 : (i64) -> !llvm.ptr
        llvm.store %196, %198 : i64, !llvm.ptr
        cf.br ^bb33
        ^bb33:
        %199 = llvm.load %198 : !llvm.ptr -> i64
        %200 = llvm.mlir.addressof @QMAX : !llvm.ptr
        %201 = llvm.load %200 : !llvm.ptr -> i64
        %202 = arith.cmpi sle, %199, %201 : i64
        cf.cond_br %202, ^bb34, ^bb35
        ^bb34:
          %203 = arith.constant 1 : i32
          %204 = llvm.load %198 : !llvm.ptr -> i64
          %205 = arith.extsi %203 : i32 to i64
          %206 = llvm.getelementptr %170[%204] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %205, %206 : i64, !llvm.ptr
          %207 = llvm.load %198 : !llvm.ptr -> i64
          %208 = llvm.load %181 : !llvm.ptr -> i64
          %209 = arith.addi %207, %208 : i64
          llvm.store %209, %198 : i64, !llvm.ptr
          cf.br ^bb33
        ^bb35:
        cf.br ^bb32
      ^bb31:
        cf.br ^bb32
      ^bb32:
      %210 = llvm.load %181 : !llvm.ptr -> i64
      %211 = arith.constant 1 : i32
      %213 = arith.extsi %211 : i32 to i64
      %212 = arith.addi %210, %213 : i64
      llvm.store %212, %181 : i64, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    %215 = arith.constant 64 : i32
    %216 = arith.constant 8 : i32
    %217 = arith.extsi %215 : i32 to i64
    %218 = arith.extsi %216 : i32 to i64
    %214 = func.call @calloc(%217, %218) : (i64, i64) -> !llvm.ptr
    %220 = arith.constant 64 : i32
    %221 = arith.constant 8 : i32
    %222 = arith.extsi %220 : i32 to i64
    %223 = arith.extsi %221 : i32 to i64
    %219 = func.call @calloc(%222, %223) : (i64, 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
    %228 = arith.constant 5 : i32
    %229 = arith.extsi %228 : i32 to i64
    llvm.store %229, %181 : i64, !llvm.ptr
    cf.br ^bb36
    ^bb36:
    %230 = llvm.load %181 : !llvm.ptr -> i64
    %231 = llvm.mlir.addressof @QMAX : !llvm.ptr
    %232 = llvm.load %231 : !llvm.ptr -> i64
    %233 = arith.cmpi sle, %230, %232 : i64
    cf.cond_br %233, ^bb37, ^bb38
    ^bb37:
      %235 = llvm.load %181 : !llvm.ptr -> i64
      %236 = llvm.getelementptr %170[%235] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %234 = llvm.load %236 : !llvm.ptr -> i64
      %237 = arith.constant 0 : i32
      %239 = arith.extsi %237 : i32 to i64
      %238 = arith.cmpi eq, %234, %239 : i64
      %240 = scf.if %238 -> (i1) {
        %241 = llvm.load %181 : !llvm.ptr -> i64
        %242 = arith.constant 1 : i32
        %244 = arith.extsi %242 : i32 to i64
        %243 = arith.subi %241, %244 : i64
        %245 = llvm.mlir.addressof @CAP : !llvm.ptr
        %246 = llvm.load %245 : !llvm.ptr -> i64
        %247 = arith.cmpi sle, %243, %246 : i64
        scf.yield %247 : i1
      } else {
        %248 = arith.constant false
        scf.yield %248 : i1
      }
      %249 = scf.if %240 -> (i1) {
        %250 = llvm.load %181 : !llvm.ptr -> i64
        %251 = llvm.mlir.addressof @P : !llvm.ptr
        %252 = llvm.load %251 : !llvm.ptr -> i64
        %253 = arith.cmpi slt, %250, %252 : i64
        scf.yield %253 : i1
      } else {
        %254 = arith.constant false
        scf.yield %254 : i1
      }
      cf.cond_br %249, ^bb39, ^bb40
      ^bb39:
        %255 = llvm.load %181 : !llvm.ptr -> i64
        %256 = llvm.load %227 : !llvm.ptr -> i64
        %257 = llvm.getelementptr %214[%256] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %255, %257 : i64, !llvm.ptr
        %259 = llvm.load %181 : !llvm.ptr -> i64
        %260 = llvm.mlir.addressof @P : !llvm.ptr
        %261 = llvm.load %260 : !llvm.ptr -> i64
        %262 = arith.constant 2 : i32
        %264 = arith.extsi %262 : i32 to i64
        %263 = arith.subi %261, %264 : i64
        %258 = func.call @modpow(%259, %263) : (i64, i64) -> i64
        %265 = llvm.load %227 : !llvm.ptr -> i64
        %266 = llvm.getelementptr %219[%265] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %258, %266 : i64, !llvm.ptr
        %267 = llvm.load %227 : !llvm.ptr -> i64
        %268 = arith.constant 1 : i32
        %270 = arith.extsi %268 : i32 to i64
        %269 = arith.addi %267, %270 : i64
        llvm.store %269, %227 : i64, !llvm.ptr
        cf.br ^bb41
      ^bb40:
        cf.br ^bb41
      ^bb41:
      %271 = llvm.load %181 : !llvm.ptr -> i64
      %272 = arith.constant 1 : i32
      %274 = arith.extsi %272 : i32 to i64
      %273 = arith.addi %271, %274 : i64
      llvm.store %273, %181 : i64, !llvm.ptr
      cf.br ^bb36
    ^bb38:
    %276 = llvm.mlir.addressof @HB : !llvm.ptr
    %277 = llvm.load %276 : !llvm.ptr -> i64
    %278 = arith.constant 8 : i32
    %279 = arith.extsi %278 : i32 to i64
    %275 = func.call @calloc(%277, %279) : (i64, i64) -> !llvm.ptr
    %281 = llvm.mlir.addressof @HB : !llvm.ptr
    %282 = llvm.load %281 : !llvm.ptr -> i64
    %283 = arith.constant 8 : i32
    %284 = arith.extsi %283 : i32 to i64
    %280 = func.call @calloc(%282, %284) : (i64, i64) -> !llvm.ptr
    %285 = arith.constant 0 : i32
    %286 = arith.extsi %285 : i32 to i64
    %287 = llvm.mlir.constant(1 : i64) : i64
    %288 = llvm.alloca %287 x i64 : (i64) -> !llvm.ptr
    llvm.store %286, %288 : i64, !llvm.ptr
    %289 = arith.constant 1 : i32
    %290 = arith.extsi %289 : i32 to i64
    %291 = llvm.mlir.constant(1 : i64) : i64
    %292 = llvm.alloca %291 x i64 : (i64) -> !llvm.ptr
    llvm.store %290, %292 : i64, !llvm.ptr
    cf.br ^bb42
    ^bb42:
    %293 = arith.constant 2 : i32
    %294 = llvm.load %288 : !llvm.ptr -> i64
    %296 = arith.extsi %293 : i32 to i64
    %295 = arith.muli %296, %294 : i64
    %297 = llvm.mlir.addressof @CAP : !llvm.ptr
    %298 = llvm.load %297 : !llvm.ptr -> i64
    %299 = arith.cmpi sle, %295, %298 : i64
    cf.cond_br %299, ^bb43, ^bb44
    ^bb43:
      %300 = llvm.load %292 : !llvm.ptr -> 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 0 : 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 ^bb45
      ^bb45:
      %307 = llvm.load %306 : !llvm.ptr -> i64
      %308 = arith.constant 2 : i32
      %309 = llvm.load %288 : !llvm.ptr -> i64
      %311 = arith.extsi %308 : i32 to i64
      %310 = arith.muli %311, %309 : i64
      %312 = arith.addi %307, %310 : i64
      %313 = llvm.mlir.addressof @CAP : !llvm.ptr
      %314 = llvm.load %313 : !llvm.ptr -> i64
      %315 = arith.cmpi sle, %312, %314 : i64
      cf.cond_br %315, ^bb46, ^bb47
      ^bb46:
        %317 = llvm.load %302 : !llvm.ptr -> i64
        %316 = func.call @hslot(%275, %317) : (!llvm.ptr, i64) -> i64
        %319 = llvm.getelementptr %275[%316] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %318 = llvm.load %319 : !llvm.ptr -> i64
        %320 = arith.constant 0 : i32
        %322 = arith.extsi %320 : i32 to i64
        %321 = arith.cmpi eq, %318, %322 : i64
        cf.cond_br %321, ^bb48, ^bb49
        ^bb48:
          %323 = llvm.load %302 : !llvm.ptr -> i64
          %324 = llvm.getelementptr %275[%316] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %323, %324 : i64, !llvm.ptr
          %325 = llvm.load %306 : !llvm.ptr -> i64
          %326 = arith.constant 2 : i32
          %327 = llvm.load %288 : !llvm.ptr -> i64
          %329 = arith.extsi %326 : i32 to i64
          %328 = arith.muli %329, %327 : i64
          %330 = arith.addi %325, %328 : i64
          %331 = llvm.getelementptr %280[%316] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %330, %331 : i64, !llvm.ptr
          cf.br ^bb50
        ^bb49:
          %332 = llvm.load %306 : !llvm.ptr -> i64
          %333 = arith.constant 2 : i32
          %334 = llvm.load %288 : !llvm.ptr -> i64
          %336 = arith.extsi %333 : i32 to i64
          %335 = arith.muli %336, %334 : i64
          %337 = arith.addi %332, %335 : i64
          %339 = llvm.getelementptr %280[%316] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %338 = llvm.load %339 : !llvm.ptr -> i64
          %340 = arith.cmpi slt, %337, %338 : i64
          cf.cond_br %340, ^bb51, ^bb52
          ^bb51:
            %341 = llvm.load %306 : !llvm.ptr -> i64
            %342 = arith.constant 2 : i32
            %343 = llvm.load %288 : !llvm.ptr -> i64
            %345 = arith.extsi %342 : i32 to i64
            %344 = arith.muli %345, %343 : i64
            %346 = arith.addi %341, %344 : i64
            %347 = llvm.getelementptr %280[%316] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            llvm.store %346, %347 : i64, !llvm.ptr
            cf.br ^bb53
          ^bb52:
            cf.br ^bb53
          ^bb53:
          cf.br ^bb50
        ^bb50:
        %349 = llvm.load %302 : !llvm.ptr -> i64
        %350 = arith.constant 2 : i32
        %351 = arith.extsi %350 : i32 to i64
        %348 = func.call @mulmod(%349, %351) : (i64, i64) -> i64
        llvm.store %348, %302 : i64, !llvm.ptr
        %352 = llvm.load %306 : !llvm.ptr -> i64
        %353 = arith.constant 1 : i32
        %355 = arith.extsi %353 : i32 to i64
        %354 = arith.addi %352, %355 : i64
        llvm.store %354, %306 : i64, !llvm.ptr
        cf.br ^bb45
      ^bb47:
      %357 = llvm.load %292 : !llvm.ptr -> i64
      %358 = arith.constant 3 : i32
      %359 = arith.extsi %358 : i32 to i64
      %356 = func.call @mulmod(%357, %359) : (i64, i64) -> i64
      llvm.store %356, %292 : i64, !llvm.ptr
      %360 = llvm.load %288 : !llvm.ptr -> i64
      %361 = arith.constant 1 : i32
      %363 = arith.extsi %361 : i32 to i64
      %362 = arith.addi %360, %363 : i64
      llvm.store %362, %288 : i64, !llvm.ptr
      cf.br ^bb42
    ^bb44:
    %365 = arith.constant 8 : i32
    %366 = arith.constant 8 : i32
    %367 = arith.extsi %365 : i32 to i64
    %368 = arith.extsi %366 : i32 to i64
    %364 = func.call @calloc(%367, %368) : (i64, i64) -> !llvm.ptr
    %370 = arith.constant 64 : i32
    %371 = arith.constant 8 : i32
    %372 = arith.extsi %370 : i32 to i64
    %373 = arith.extsi %371 : i32 to i64
    %369 = func.call @calloc(%372, %373) : (i64, i64) -> !llvm.ptr
    %375 = arith.constant 64 : i32
    %376 = arith.constant 8 : i32
    %377 = arith.extsi %375 : i32 to i64
    %378 = arith.extsi %376 : i32 to i64
    %374 = func.call @calloc(%377, %378) : (i64, i64) -> !llvm.ptr
    %379 = llvm.mlir.addressof @CAP : !llvm.ptr
    %380 = llvm.load %379 : !llvm.ptr -> i64
    %381 = arith.constant 1 : i32
    %383 = arith.extsi %381 : i32 to i64
    %382 = arith.addi %380, %383 : i64
    %384 = arith.constant 0 : i32
    %385 = arith.extsi %384 : i32 to i64
    %386 = llvm.getelementptr %364[%385] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %382, %386 : i64, !llvm.ptr
    %388 = arith.constant 0 : i32
    %389 = arith.constant 1 : i32
    %390 = arith.constant 0 : i32
    %391 = arith.constant 0 : i32
    %392 = llvm.load %227 : !llvm.ptr -> i64
    %393 = arith.extsi %388 : i32 to i64
    %394 = arith.extsi %389 : i32 to i64
    %395 = arith.extsi %390 : i32 to i64
    %396 = arith.extsi %391 : i32 to i64
    %387 = func.call @dfs(%393, %394, %395, %396, %214, %219, %392, %275, %280, %364, %369, %374) : (i64, i64, i64, i64, !llvm.ptr, !llvm.ptr, i64, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr) -> i64
    %397 = arith.constant 1 : i32
    %398 = arith.extsi %397 : i32 to i128
    %399 = llvm.mlir.constant(1 : i64) : i64
    %400 = llvm.alloca %399 x i128 : (i64) -> !llvm.ptr
    llvm.store %398, %400 : i128, !llvm.ptr
    %401 = arith.constant 0 : i32
    %402 = arith.extsi %401 : i32 to i64
    %403 = llvm.mlir.constant(1 : i64) : i64
    %404 = llvm.alloca %403 x i64 : (i64) -> !llvm.ptr
    llvm.store %402, %404 : i64, !llvm.ptr
    cf.br ^bb54
    ^bb54:
    %405 = llvm.load %404 : !llvm.ptr -> i64
    %407 = arith.constant 4 : i32
    %408 = arith.extsi %407 : i32 to i64
    %409 = llvm.getelementptr %364[%408] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %406 = llvm.load %409 : !llvm.ptr -> i64
    %410 = arith.cmpi slt, %405, %406 : i64
    cf.cond_br %410, ^bb55, ^bb56
    ^bb55:
      %411 = llvm.load %400 : !llvm.ptr -> i128
      %413 = llvm.load %404 : !llvm.ptr -> i64
      %414 = llvm.getelementptr %374[%413] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %412 = llvm.load %414 : !llvm.ptr -> i64
      %415 = arith.extsi %412 : i64 to i128
      %417 = arith.trunci %411 : i128 to i64
      %418 = arith.trunci %415 : i128 to i64
      %416 = arith.muli %417, %418 : i64
      %419 = arith.extsi %416 : i64 to i128
      llvm.store %419, %400 : i128, !llvm.ptr
      %420 = llvm.load %404 : !llvm.ptr -> i64
      %421 = arith.constant 1 : i32
      %423 = arith.extsi %421 : i32 to i64
      %422 = arith.addi %420, %423 : i64
      llvm.store %422, %404 : i64, !llvm.ptr
      cf.br ^bb54
    ^bb56:
    %425 = arith.constant 0 : i32
    %426 = arith.extsi %425 : i32 to i64
    %427 = llvm.getelementptr %364[%426] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %424 = llvm.load %427 : !llvm.ptr -> i64
    %429 = arith.constant 2 : i32
    %430 = arith.extsi %429 : i32 to i64
    %431 = llvm.getelementptr %364[%430] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %428 = llvm.load %431 : !llvm.ptr -> i64
    %432 = arith.subi %424, %428 : i64
    %434 = arith.constant 3 : i32
    %435 = arith.extsi %434 : i32 to i64
    %436 = llvm.getelementptr %364[%435] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    %433 = llvm.load %436 : !llvm.ptr -> i64
    %437 = arith.constant 1 : i32
    %439 = arith.constant 0 : i32
    %438 = arith.subi %439, %437 : i32
    %440 = arith.extsi %438 : i32 to i64
    %441 = llvm.mlir.constant(1 : i64) : i64
    %442 = llvm.alloca %441 x i64 : (i64) -> !llvm.ptr
    llvm.store %440, %442 : i64, !llvm.ptr
    %443 = arith.constant 1 : i32
    %445 = arith.constant 0 : i32
    %444 = arith.subi %445, %443 : i32
    %446 = arith.extsi %444 : i32 to i64
    %447 = llvm.mlir.constant(1 : i64) : i64
    %448 = llvm.alloca %447 x i64 : (i64) -> !llvm.ptr
    llvm.store %446, %448 : i64, !llvm.ptr
    %449 = arith.constant 0 : i32
    %450 = arith.extsi %449 : i32 to i64
    llvm.store %450, %288 : i64, !llvm.ptr
    %451 = arith.constant 1 : i32
    %452 = arith.extsi %451 : i32 to i64
    llvm.store %452, %292 : i64, !llvm.ptr
    cf.br ^bb57
    ^bb57:
    %453 = arith.constant 2 : i32
    %454 = llvm.load %288 : !llvm.ptr -> i64
    %456 = arith.extsi %453 : i32 to i64
    %455 = arith.muli %456, %454 : i64
    %457 = arith.cmpi sle, %455, %432 : i64
    cf.cond_br %457, ^bb58, ^bb59
    ^bb58:
      %458 = llvm.load %292 : !llvm.ptr -> i64
      %459 = llvm.mlir.constant(1 : i64) : i64
      %460 = llvm.alloca %459 x i64 : (i64) -> !llvm.ptr
      llvm.store %458, %460 : i64, !llvm.ptr
      %461 = arith.constant 0 : i32
      %462 = arith.extsi %461 : i32 to i64
      %463 = llvm.mlir.constant(1 : i64) : i64
      %464 = llvm.alloca %463 x i64 : (i64) -> !llvm.ptr
      llvm.store %462, %464 : i64, !llvm.ptr
      cf.br ^bb60
      ^bb60:
      %465 = llvm.load %464 : !llvm.ptr -> i64
      %466 = arith.constant 2 : i32
      %467 = llvm.load %288 : !llvm.ptr -> i64
      %469 = arith.extsi %466 : i32 to i64
      %468 = arith.muli %469, %467 : i64
      %470 = arith.addi %465, %468 : i64
      %471 = arith.cmpi sle, %470, %432 : i64
      cf.cond_br %471, ^bb61, ^bb62
      ^bb61:
        %472 = llvm.load %460 : !llvm.ptr -> i64
        %473 = arith.cmpi eq, %472, %433 : i64
        %474 = scf.if %473 -> (i1) {
          %475 = llvm.load %464 : !llvm.ptr -> i64
          %476 = arith.constant 2 : i32
          %477 = llvm.load %288 : !llvm.ptr -> i64
          %479 = arith.extsi %476 : i32 to i64
          %478 = arith.muli %479, %477 : i64
          %480 = arith.addi %475, %478 : i64
          %481 = arith.cmpi eq, %480, %432 : i64
          scf.yield %481 : i1
        } else {
          %482 = arith.constant false
          scf.yield %482 : i1
        }
        cf.cond_br %474, ^bb63, ^bb64
        ^bb63:
          %483 = llvm.load %464 : !llvm.ptr -> i64
          llvm.store %483, %442 : i64, !llvm.ptr
          %484 = llvm.load %288 : !llvm.ptr -> i64
          llvm.store %484, %448 : i64, !llvm.ptr
          cf.br ^bb65
        ^bb64:
          cf.br ^bb65
        ^bb65:
        %486 = llvm.load %460 : !llvm.ptr -> i64
        %487 = arith.constant 2 : i32
        %488 = arith.extsi %487 : i32 to i64
        %485 = func.call @mulmod(%486, %488) : (i64, i64) -> i64
        llvm.store %485, %460 : i64, !llvm.ptr
        %489 = llvm.load %464 : !llvm.ptr -> i64
        %490 = arith.constant 1 : i32
        %492 = arith.extsi %490 : i32 to i64
        %491 = arith.addi %489, %492 : i64
        llvm.store %491, %464 : i64, !llvm.ptr
        cf.br ^bb60
      ^bb62:
      %494 = llvm.load %292 : !llvm.ptr -> i64
      %495 = arith.constant 3 : i32
      %496 = arith.extsi %495 : i32 to i64
      %493 = func.call @mulmod(%494, %496) : (i64, i64) -> i64
      llvm.store %493, %292 : i64, !llvm.ptr
      %497 = llvm.load %288 : !llvm.ptr -> i64
      %498 = arith.constant 1 : i32
      %500 = arith.extsi %498 : i32 to i64
      %499 = arith.addi %497, %500 : i64
      llvm.store %499, %288 : i64, !llvm.ptr
      cf.br ^bb57
    ^bb59:
    %501 = arith.constant 0 : i32
    %502 = arith.extsi %501 : i32 to i64
    llvm.store %502, %404 : i64, !llvm.ptr
    cf.br ^bb66
    ^bb66:
    %503 = llvm.load %404 : !llvm.ptr -> i64
    %504 = llvm.load %442 : !llvm.ptr -> i64
    %505 = arith.cmpi slt, %503, %504 : i64
    cf.cond_br %505, ^bb67, ^bb68
    ^bb67:
      %506 = llvm.load %400 : !llvm.ptr -> i128
      %507 = arith.constant 2 : i32
      %508 = arith.extsi %507 : i32 to i128
      %510 = arith.trunci %506 : i128 to i64
      %511 = arith.trunci %508 : i128 to i64
      %509 = arith.muli %510, %511 : i64
      %512 = arith.extsi %509 : i64 to i128
      llvm.store %512, %400 : i128, !llvm.ptr
      %513 = llvm.load %404 : !llvm.ptr -> i64
      %514 = arith.constant 1 : i32
      %516 = arith.extsi %514 : i32 to i64
      %515 = arith.addi %513, %516 : i64
      llvm.store %515, %404 : i64, !llvm.ptr
      cf.br ^bb66
    ^bb68:
    %517 = arith.constant 0 : i32
    %518 = arith.extsi %517 : i32 to i64
    llvm.store %518, %404 : i64, !llvm.ptr
    cf.br ^bb69
    ^bb69:
    %519 = llvm.load %404 : !llvm.ptr -> i64
    %520 = llvm.load %448 : !llvm.ptr -> i64
    %521 = arith.cmpi slt, %519, %520 : i64
    cf.cond_br %521, ^bb70, ^bb71
    ^bb70:
      %522 = llvm.load %400 : !llvm.ptr -> i128
      %523 = arith.constant 3 : i32
      %524 = arith.extsi %523 : i32 to i128
      %526 = arith.trunci %522 : i128 to i64
      %527 = arith.trunci %524 : i128 to i64
      %525 = arith.muli %526, %527 : i64
      %528 = arith.extsi %525 : i64 to i128
      llvm.store %528, %400 : i128, !llvm.ptr
      %529 = llvm.load %404 : !llvm.ptr -> i64
      %530 = arith.constant 1 : i32
      %532 = arith.extsi %530 : i32 to i64
      %531 = arith.addi %529, %532 : i64
      llvm.store %531, %404 : i64, !llvm.ptr
      cf.br ^bb69
    ^bb71:
    %534 = arith.constant 64 : i32
    %535 = arith.constant 8 : i32
    %536 = arith.extsi %534 : i32 to i64
    %537 = arith.extsi %535 : i32 to i64
    %533 = func.call @calloc(%536, %537) : (i64, i64) -> !llvm.ptr
    %538 = arith.constant 0 : i32
    %539 = arith.extsi %538 : i32 to i64
    %540 = llvm.mlir.constant(1 : i64) : i64
    %541 = llvm.alloca %540 x i64 : (i64) -> !llvm.ptr
    llvm.store %539, %541 : i64, !llvm.ptr
    %542 = llvm.load %400 : !llvm.ptr -> i128
    %543 = llvm.mlir.constant(1 : i64) : i64
    %544 = llvm.alloca %543 x i128 : (i64) -> !llvm.ptr
    llvm.store %542, %544 : i128, !llvm.ptr
    cf.br ^bb72
    ^bb72:
    %545 = llvm.load %544 : !llvm.ptr -> i128
    %546 = arith.constant 0 : i32
    %547 = arith.extsi %546 : i32 to i128
    %549 = arith.trunci %545 : i128 to i64
    %550 = arith.trunci %547 : i128 to i64
    %548 = arith.cmpi sgt, %549, %550 : i64
    cf.cond_br %548, ^bb73, ^bb74
    ^bb73:
      %551 = llvm.load %544 : !llvm.ptr -> i128
      %552 = arith.constant 10 : i32
      %553 = arith.extsi %552 : i32 to i128
      %555 = arith.trunci %551 : i128 to i64
      %556 = arith.trunci %553 : i128 to i64
      %554 = arith.remsi %555, %556 : i64
      %557 = llvm.load %541 : !llvm.ptr -> i64
      %558 = llvm.getelementptr %533[%557] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %554, %558 : i64, !llvm.ptr
      %559 = llvm.load %544 : !llvm.ptr -> i128
      %560 = arith.constant 10 : i32
      %561 = arith.extsi %560 : i32 to i128
      %563 = arith.trunci %559 : i128 to i64
      %564 = arith.trunci %561 : i128 to i64
      %562 = arith.divsi %563, %564 : i64
      %565 = arith.extsi %562 : i64 to i128
      llvm.store %565, %544 : i128, !llvm.ptr
      %566 = llvm.load %541 : !llvm.ptr -> i64
      %567 = arith.constant 1 : i32
      %569 = arith.extsi %567 : i32 to i64
      %568 = arith.addi %566, %569 : i64
      llvm.store %568, %541 : i64, !llvm.ptr
      cf.br ^bb72
    ^bb74:
    %570 = llvm.load %541 : !llvm.ptr -> i64
    %571 = arith.constant 1 : i32
    %573 = arith.extsi %571 : i32 to i64
    %572 = arith.subi %570, %573 : i64
    %574 = llvm.mlir.constant(1 : i64) : i64
    %575 = llvm.alloca %574 x i64 : (i64) -> !llvm.ptr
    llvm.store %572, %575 : i64, !llvm.ptr
    cf.br ^bb75
    ^bb75:
    %576 = llvm.load %575 : !llvm.ptr -> i64
    %577 = arith.constant 0 : i32
    %579 = arith.extsi %577 : i32 to i64
    %578 = arith.cmpi sge, %576, %579 : i64
    cf.cond_br %578, ^bb76, ^bb77
    ^bb76:
      %580 = llvm.mlir.addressof @str_0 : !llvm.ptr
      %581 = arith.constant 48 : i32
      %583 = llvm.load %575 : !llvm.ptr -> i64
      %584 = llvm.getelementptr %533[%583] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %582 = llvm.load %584 : !llvm.ptr -> i64
      %586 = arith.extsi %581 : i32 to i64
      %585 = arith.addi %586, %582 : i64
      %587 = arith.trunci %585 : i64 to i32
      %588 = llvm.call @printf(%580, %587) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i32) -> i32
      %589 = llvm.load %575 : !llvm.ptr -> i64
      %590 = arith.constant 1 : i32
      %592 = arith.extsi %590 : i32 to i64
      %591 = arith.subi %589, %592 : i64
      llvm.store %591, %575 : i64, !llvm.ptr
      cf.br ^bb75
    ^bb77:
    %593 = llvm.mlir.addressof @str_1 : !llvm.ptr
    %594 = llvm.call @printf(%593) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr) -> i32
    func.call @free(%170) : (!llvm.ptr) -> ()
    func.call @free(%214) : (!llvm.ptr) -> ()
    func.call @free(%219) : (!llvm.ptr) -> ()
    func.call @free(%275) : (!llvm.ptr) -> ()
    func.call @free(%280) : (!llvm.ptr) -> ()
    func.call @free(%364) : (!llvm.ptr) -> ()
    func.call @free(%369) : (!llvm.ptr) -> ()
    func.call @free(%374) : (!llvm.ptr) -> ()
    func.call @free(%533) : (!llvm.ptr) -> ()
    %604 = arith.constant 0 : i32
    func.return %604 : i32
  }
}