Problem 612

Friend numbers: f(10^18) mod 1000267129 via digit-mask DP.

Answer819963842
Output819963842
StatusPASS
Native helperno
Runtime0 ms
Peak memory1136 KB
Time complexityO(n^2) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

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

Flow source

# Project Euler 612
# Friend numbers: f(10^18) mod 1000267129 via digit-mask DP.

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

const MOD: i64 = 1000267129
const MASKS: i64 = 1024
const SZ: i64 = 4096

function main() -> i32 {
    let m: i64 = 999999999999999999
    let digs: ptr<i32> = calloc(20, 4)
    let mut tmp: i64 = m
    let mut nd: i64 = 0
    while tmp > 0 {
        digs[nd] = (tmp % 10) as i32
        tmp = tmp / 10
        nd = nd + 1
    }
    let mut a: i64 = 0
    let mut b: i64 = nd - 1
    while a < b {
        let t: i32 = digs[a]
        digs[a] = digs[b]
        digs[b] = t
        a = a + 1
        b = b - 1
    }

    let dp: ptr<i64> = calloc(SZ, 8)
    let nxt: ptr<i64> = calloc(SZ, 8)
    if dp == null || nxt == null { return 1 }
    # key = mask*4 + started*2 + tight
    dp[1] = 1

    let mut di: i64 = 0
    while di < nd {
        let lim_digit: i64 = digs[di] as i64
        let mut k: i64 = 0
        while k < SZ {
            nxt[k] = 0
            k = k + 1
        }
        k = 0
        while k < SZ {
            let cnt: i64 = dp[k]
            if cnt != 0 {
                let mask: i64 = k / 4
                let started: i64 = (k / 2) % 2
                let tight: i64 = k % 2
                let mut lim: i64 = 9
                if tight == 1 { lim = lim_digit }
                let mut d: i64 = 0
                while d <= lim {
                    let mut ntight: i64 = 0
                    if tight == 1 && d == lim { ntight = 1 }
                    let mut nmask: i64 = 0
                    let mut nstarted: i64 = 0
                    if started == 0 && d == 0 {
                        nmask = 0
                        nstarted = 0
                    } else {
                        if started == 0 {
                            nmask = 1 << d
                        } else {
                            nmask = mask | (1 << d)
                        }
                        nstarted = 1
                    }
                    let nkey: i64 = nmask * 4 + nstarted * 2 + ntight
                    nxt[nkey] = nxt[nkey] + cnt
                    d = d + 1
                }
            }
            k = k + 1
        }
        let sw: ptr<i64> = dp
        dp = nxt
        nxt = sw
        di = di + 1
    }

    let counts: ptr<i64> = calloc(MASKS, 8)
    let mut k: i64 = 0
    while k < SZ {
        let started: i64 = (k / 2) % 2
        if started == 1 && dp[k] != 0 {
            counts[k / 4] = counts[k / 4] + dp[k]
        }
        k = k + 1
    }

    let mut disjoint: i128 = 0
    a = 1
    while a < MASKS {
        let ca: i64 = counts[a]
        if ca != 0 {
            b = a + 1
            while b < MASKS {
                if (a & b) == 0 {
                    disjoint = disjoint + (ca as i128) * (counts[b] as i128)
                }
                b = b + 1
            }
        }
        a = a + 1
    }
    let tp: i128 = (m as i128) * ((m - 1) as i128) / 2
    let friend: i128 = tp - disjoint
    let mut ans: i64 = (friend % (MOD as i128)) as i64
    if ans < 0 { ans = ans + MOD }
    printf("%lld\n", ans)
    free(digs)
    free(dp)
    free(nxt)
    free(counts)
    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 main(void);

static const int64_t MOD = 1000267129;
static const int64_t MASKS = 1024;
static const int64_t SZ = 4096;



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