Problem 990

DP over decimal columns with signed carry, mod 1e9+7.

Answer50322750
Output50322750
StatusPASS
Native helperno
Runtime240 ms
Peak memory537808 KB
Time complexityO(n^4) (estimated)
Space complexityO(n^2) (estimated)

Performance comparison

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

Flow source

# Project Euler 990: Digit Equations
# DP over decimal columns with signed carry, mod 1e9+7.

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
    function memset(p: ptr<void>, c: i32, n: i64) -> ptr<void>
    function memcpy(dst: ptr<void>, src: ptr<void>, n: i64) -> ptr<void>
}

const MOD: i64 = 1000000007
const MAX_N: i32 = 50
const MAX_TERMS: i32 = 25
const MAX_CARRY: i32 = 25
const CARRY_RANGE: i32 = 51
const MAX_DEG: i32 = 851

function mod_add(a: i64, b: i64) -> i64 {
    let mut r: i64 = a + b
    if r >= MOD { r = r - MOD }
    return r
}

function mod_mul(a: i64, b: i64) -> i64 {
    return ((a as i128) * (b as i128) % MOD) as i64
}

# Flat index helpers
function binom_idx(n: i32, k: i32) -> i64 {
    return (n as i64) * 26 + (k as i64)
}

function st_idx(p: i32, q: i32, d: i32) -> i64 {
    return (p as i64) * 51 * 851 + (q as i64) * 851 + (d as i64)
}

function stl_idx(p: i32, q: i32) -> i64 {
    return (p as i64) * 51 + (q as i64)
}

function trans_idx(al: i32, ar: i32, ci: i32) -> i64 {
    return (al as i64) * 26 * 51 + (ar as i64) * 51 + (ci as i64)
}

function dp_idx(used: i32, al: i32, ar: i32, ci: i32) -> i64 {
    return (used as i64) * 26 * 26 * 51 + (al as i64) * 26 * 51 + (ar as i64) * 51 + (ci as i64)
}

function convolve_small(poly: ptr<i64>, plen: i32, width: i32, out: ptr<i64>, out_len: ptr<i32>) -> void {
    let n: i32 = plen + width - 1
    let mut i: i32 = 0
    while i < n {
        out[i] = 0
        i = i + 1
    }
    i = 0
    while i < plen {
        if poly[i] != 0 {
            let mut d: i32 = 0
            while d < width {
                out[i + d] = mod_add(out[i + d], poly[i])
                d = d + 1
            }
        }
        i = i + 1
    }
    out_len[0] = n
}

function main() -> i32 {
    # Build binom
    let binom: ptr<i64> = calloc(26 * 26, 8)
    let mut n: i32 = 0
    while n <= MAX_TERMS {
        binom[binom_idx(n, 0)] = 1
        binom[binom_idx(n, n)] = 1
        let mut k: i32 = 1
        while k < n {
            binom[binom_idx(n, k)] = mod_add(binom[binom_idx(n - 1, k - 1)], binom[binom_idx(n - 1, k)])
            k = k + 1
        }
        n = n + 1
    }

    # Build sum_tables
    let sum_tables: ptr<i64> = calloc(51 * 51 * 851, 8)
    let sum_table_len: ptr<i32> = calloc(51 * 51, 4)

    # ways[p] = convolution of p copies of [1]*10
    let ways: ptr<ptr<i64> > = calloc(51, 8) as ptr<ptr<i64> >
    let mut p: i32 = 0
    while p <= 50 {
        ways[p] = calloc(MAX_DEG, 8)
        p = p + 1
    }
    let tmp: ptr<i64> = calloc(MAX_DEG, 8)
    let len_out: ptr<i32> = calloc(1, 4)
    let ways_len: ptr<i32> = calloc(51, 4)

    ways[0][0] = 1
    ways_len[0] = 1
    p = 1
    while p <= 2 * MAX_TERMS {
        convolve_small(ways[p - 1], ways_len[p - 1], 10, ways[p], len_out)
        ways_len[p] = len_out[0]
        p = p + 1
    }

    p = 0
    while p <= 2 * MAX_TERMS {
        # sum_tables[p][0] = ways[p]
        memcpy(sum_tables + st_idx(p, 0, 0), ways[p], (ways_len[p] as i64) * 8)
        sum_table_len[stl_idx(p, 0)] = ways_len[p]
        let mut q: i32 = 1
        while q <= 2 * MAX_TERMS {
            convolve_small(sum_tables + st_idx(p, q - 1, 0), sum_table_len[stl_idx(p, q - 1)], 9,
                          sum_tables + st_idx(p, q, 0), len_out)
            sum_table_len[stl_idx(p, q)] = len_out[0]
            q = q + 1
        }
        p = p + 1
    }

    # Transition storage: flat arrays
    let trans_data: ptr<ptr<i64> > = calloc(26 * 26 * 51, 8) as ptr<ptr<i64> >
    let trans_count_arr: ptr<i32> = calloc(26 * 26 * 51, 4)
    let trans_computed_arr: ptr<i8> = calloc(26 * 26 * 51, 1)

    # DP array
    let dp: ptr<i64> = calloc(51 * 26 * 26 * 51, 8)

    let limit: i32 = MAX_N

    # Initial states
    let mut lt: i32 = 1
    while lt <= MAX_TERMS {
        let mut rt: i32 = 1
        while rt <= MAX_TERMS {
            let base_length: i32 = lt + rt - 1
            if base_length <= limit {
                let idx: i64 = dp_idx(base_length, lt, rt, MAX_CARRY)
                dp[idx] = mod_add(dp[idx], 1)
            }
            rt = rt + 1
        }
        lt = lt + 1
    }

    let mut answer: i64 = 0
    let mut used: i32 = 0
    while used <= limit {
        answer = mod_add(answer, dp[dp_idx(used, 0, 0, MAX_CARRY)])

        let mut al: i32 = 0
        while al <= MAX_TERMS {
            let mut ar: i32 = 0
            while ar <= MAX_TERMS {
                if al == 0 && ar == 0 {
                    ar = ar + 1
                    continue
                }
                let mut ci: i32 = 0
                while ci < CARRY_RANGE {
                    let ways_val: i64 = dp[dp_idx(used, al, ar, ci)]
                    if ways_val == 0 {
                        ci = ci + 1
                        continue
                    }
                    let carry: i32 = ci - MAX_CARRY

                    # Compute transitions if not done
                    let tidx: i64 = trans_idx(al, ar, ci)
                    if trans_computed_arr[tidx] == 0 {
                        trans_computed_arr[tidx] = 1

                        if al == 0 && ar == 0 {
                            trans_count_arr[tidx] = 0
                        } else {
                            # First pass: count
                            let mut count: i32 = 0
                            let mut nl: i32 = 0
                            while nl <= al {
                                let mut nr: i32 = 0
                                while nr <= ar {
                                    let continuing: i32 = nl + nr
                                    let ending: i32 = (al - nl) + (ar - nr)
                                    let ending_left: i32 = al - nl
                                    let counts: ptr<i64> = sum_tables + st_idx(continuing, ending, 0)
                                    let clen: i32 = sum_table_len[stl_idx(continuing, ending)]
                                    let base: i64 = -(carry as i64) - (ending_left as i64) + 9 * (ar as i64)
                                    let mut nc: i32 = -MAX_CARRY
                                    while nc <= MAX_CARRY {
                                        let index: i64 = 10 * (nc as i64) + base
                                        if index >= 0 && index < (clen as i64) && counts[index] != 0 {
                                            count = count + 1
                                        }
                                        nc = nc + 1
                                    }
                                    nr = nr + 1
                                }
                                nl = nl + 1
                            }

                            trans_count_arr[tidx] = count
                            if count > 0 {
                                let list: ptr<i64> = calloc((count as i64) * 4, 8)
                                let mut idx2: i32 = 0
                                nl = 0
                                while nl <= al {
                                    let choose_left: i64 = binom[binom_idx(al, nl)]
                                    let ending_left: i32 = al - nl
                                    let mut nr: i32 = 0
                                    while nr <= ar {
                                        let choose_terms: i64 = mod_mul(choose_left, binom[binom_idx(ar, nr)])
                                        let continuing: i32 = nl + nr
                                        let ending: i32 = ending_left + (ar - nr)
                                        let counts: ptr<i64> = sum_tables + st_idx(continuing, ending, 0)
                                        let clen: i32 = sum_table_len[stl_idx(continuing, ending)]
                                        let base: i64 = -(carry as i64) - (ending_left as i64) + 9 * (ar as i64)
                                        let mut nc: i32 = -MAX_CARRY
                                        while nc <= MAX_CARRY {
                                            let index: i64 = 10 * (nc as i64) + base
                                            if index >= 0 && index < (clen as i64) && counts[index] != 0 {
                                                let weight: i64 = mod_mul(choose_terms, counts[index])
                                                list[(idx2 as i64) * 4 + 0] = nl as i64
                                                list[(idx2 as i64) * 4 + 1] = nr as i64
                                                list[(idx2 as i64) * 4 + 2] = nc as i64
                                                list[(idx2 as i64) * 4 + 3] = weight
                                                idx2 = idx2 + 1
                                            }
                                            nc = nc + 1
                                        }
                                        nr = nr + 1
                                    }
                                    nl = nl + 1
                                }
                                trans_data[tidx] = list
                            }
                        }
                    }

                    let cnt: i32 = trans_count_arr[tidx]
                    let next_length: i32 = used + al + ar
                    if next_length > limit {
                        ci = ci + 1
                        continue
                    }

                    let list: ptr<i64> = trans_data[tidx]
                    let mut t: i32 = 0
                    while t < cnt {
                        let nci: i32 = (list[(t as i64) * 4 + 2]) as i32 + MAX_CARRY
                        let val: i64 = mod_mul(ways_val, list[(t as i64) * 4 + 3])
                        let nli: i32 = (list[(t as i64) * 4 + 0]) as i32
                        let nri: i32 = (list[(t as i64) * 4 + 1]) as i32
                        let di: i64 = dp_idx(next_length, nli, nri, nci)
                        dp[di] = mod_add(dp[di], val)
                        t = t + 1
                    }
                    ci = ci + 1
                }
                ar = ar + 1
            }
            al = al + 1
        }
        used = used + 1
    }

    printf("%lld\n", answer)

    # Cleanup
    p = 0
    while p <= 50 {
        free(ways[p] as ptr<void>)
        p = p + 1
    }
    free(ways as ptr<void>)
    free(tmp as ptr<void>)
    free(len_out as ptr<void>)
    free(ways_len as ptr<void>)
    free(binom as ptr<void>)
    free(sum_tables as ptr<void>)
    free(sum_table_len as ptr<void>)
    let mut ti: i64 = 0
    while ti < 26 * 26 * 51 {
        if trans_data[ti] != null {
            free(trans_data[ti] as ptr<void>)
        }
        ti = ti + 1
    }
    free(trans_data as ptr<void>)
    free(trans_count_arr as ptr<void>)
    free(trans_computed_arr as ptr<void>)
    free(dp as ptr<void>)

    return 0
}

Generated C

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Flow runtime helpers */
typedef struct flow_temp_node { struct flow_temp_node* next; } flow_temp_node;
static flow_temp_node* flow_temp_head = NULL;
static int flow_temp_atexit_set = 0;
__attribute__((unused)) static void flow_temp_free_all(void) {
    while (flow_temp_head) {
        flow_temp_node* n = flow_temp_head;
        flow_temp_head = n->next;
        free(n);
    }
}
__attribute__((unused)) static void* flow_temp_alloc(size_t nbytes) {
    flow_temp_node* node = (flow_temp_node*)malloc(sizeof(flow_temp_node) + nbytes);
    if (!node) return NULL;
    node->next = flow_temp_head;
    flow_temp_head = node;
    if (!flow_temp_atexit_set) {
        flow_temp_atexit_set = 1;
        atexit(flow_temp_free_all);
    }
    return (void*)(node + 1);
}
#ifndef FLOW_DIAG
#define FLOW_DIAG(msg) fprintf(stderr, "%s", (msg))
#endif
#ifndef FLOW_LOG
#define FLOW_LOG(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
#ifndef FLOW_LOG_EMPTY
#define FLOW_LOG_EMPTY(fmt) printf(fmt)
#endif
static char* flow_strcat(const char* a, const char* b) {
    size_t la = strlen(a ? a : ""), lb = strlen(b ? b : "");
    char* r = (char*)flow_temp_alloc(la + lb + 1);
    if (!r) return NULL;
    if (la) memcpy(r, a, la);
    if (lb) memcpy(r + la, b, lb);
    r[la + lb] = '\0';
    return r;
}

#define __flow_in_arr(arr, val) __extension__ ({ \
    int _found = 0; \
    size_t _n = sizeof(arr)/sizeof((arr)[0]); \
    for (size_t _i = 0; _i < _n; _i++) { \
        if ((arr)[_i] == (val)) { _found = 1; break; } \
    } _found; })

/* Unified fault handler (MISRA #279) — override with -DFLOW_FAULT_HANDLER=fn */
#ifndef FLOW_FAULT_HANDLER
__attribute__((unused)) static inline void flow_fault_handler(const char* msg) {
    fprintf(stderr, "flow: %s\n", msg ? msg : "fault");
    abort();
#if defined(__GNUC__) || defined(__clang__)
    __builtin_unreachable();
#endif
}
#else
#define flow_fault_handler FLOW_FAULT_HANDLER
#endif
#define flow_div_by_zero_handler() flow_fault_handler("division by zero")
#define flow_shift_ub_handler() flow_fault_handler("invalid shift (amount out of range or left-shift of negative)")

#ifndef FLOW_CHECKED_DIV
#define FLOW_CHECKED_DIV(L, R) (((R) != 0) ? ((L) / (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_MOD
#define FLOW_CHECKED_MOD(L, R) (((R) != 0) ? ((L) % (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHL
#define FLOW_CHECKED_SHL(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull)) && ((L) >= 0)) ? ((L) << (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHR
#define FLOW_CHECKED_SHR(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull))) ? ((L) >> (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif

#include <math.h>

void* _ui_state = NULL;

static inline float i32_to_f32(int32_t v) { return (float)v; }

/* Host stub for @gpu kernels (device codegen replaces this). */
static inline int32_t gpu_thread_id(void) { return 0; }

int64_t mod_add_i64_i64(int64_t a, int64_t b);
int64_t mod_mul_i64_i64(int64_t a, int64_t b);
int64_t binom_idx_i32_i32(int32_t n, int32_t k);
int64_t st_idx_i32_i32_i32(int32_t p, int32_t q, int32_t d);
int64_t stl_idx_i32_i32(int32_t p, int32_t q);
int64_t trans_idx_i32_i32_i32(int32_t al, int32_t ar, int32_t ci);
int64_t dp_idx_i32_i32_i32_i32(int32_t used, int32_t al, int32_t ar, int32_t ci);
void convolve_small_ptr_i64_i32_i32_ptr_i64_ptr_i32(int64_t* poly, int32_t plen, int32_t width, int64_t* out, int32_t* out_len);
int32_t main(void);

static const int64_t MOD = 1000000007;
static const int32_t MAX_N = 50;
static const int32_t MAX_TERMS = 25;
static const int32_t MAX_CARRY = 25;
static const int32_t CARRY_RANGE = 51;
static const int32_t MAX_DEG = 851;





int64_t mod_add_i64_i64(int64_t a, int64_t b) {
    int64_t r = (a + b);
    if (r >= MOD) {
        r = (r - MOD);
    }
    return r;
}

int64_t mod_mul_i64_i64(int64_t a, int64_t b) {
    return ((int64_t)(FLOW_CHECKED_MOD(((((__int128)(a)) * ((__int128)(b)))), (MOD))));
}

int64_t binom_idx_i32_i32(int32_t n, int32_t k) {
    return ((((int64_t)(n)) * 26) + ((int64_t)(k)));
}

int64_t st_idx_i32_i32_i32(int32_t p, int32_t q, int32_t d) {
    return ((((((int64_t)(p)) * 51) * 851) + (((int64_t)(q)) * 851)) + ((int64_t)(d)));
}

int64_t stl_idx_i32_i32(int32_t p, int32_t q) {
    return ((((int64_t)(p)) * 51) + ((int64_t)(q)));
}

int64_t trans_idx_i32_i32_i32(int32_t al, int32_t ar, int32_t ci) {
    return ((((((int64_t)(al)) * 26) * 51) + (((int64_t)(ar)) * 51)) + ((int64_t)(ci)));
}

int64_t dp_idx_i32_i32_i32_i32(int32_t used, int32_t al, int32_t ar, int32_t ci) {
    return ((((((((int64_t)(used)) * 26) * 26) * 51) + ((((int64_t)(al)) * 26) * 51)) + (((int64_t)(ar)) * 51)) + ((int64_t)(ci)));
}

void convolve_small_ptr_i64_i32_i32_ptr_i64_ptr_i32(int64_t* poly, int32_t plen, int32_t width, int64_t* out, int32_t* out_len) {
    int32_t n = ((plen + width) - 1);
    int32_t i = 0;
    while (i < n) {
        out[i] = 0;
        i = (i + 1);
    }
    i = 0;
    while (i < plen) {
        if (poly[i] != 0) {
            int32_t d = 0;
            while (d < width) {
                out[(i + d)] = mod_add_i64_i64(out[(i + d)], poly[i]);
                d = (d + 1);
            }
        }
        i = (i + 1);
    }
    out_len[0] = n;
}

int32_t main(void) {
    int64_t* binom = (int64_t*)(calloc((26 * 26), 8));
    int32_t n = 0;
    while (n <= MAX_TERMS) {
        binom[binom_idx_i32_i32(n, 0)] = 1;
        binom[binom_idx_i32_i32(n, n)] = 1;
        int32_t k = 1;
        while (k < n) {
            binom[binom_idx_i32_i32(n, k)] = mod_add_i64_i64(binom[binom_idx_i32_i32((n - 1), (k - 1))], binom[binom_idx_i32_i32((n - 1), k)]);
            k = (k + 1);
        }
        n = (n + 1);
    }
    int64_t* sum_tables = (int64_t*)(calloc(((51 * 51) * 851), 8));
    int32_t* sum_table_len = (int32_t*)(calloc((51 * 51), 4));
    int64_t** ways = (int64_t**)(((int64_t**)(calloc(51, 8))));
    int32_t p = 0;
    while (p <= 50) {
        ways[p] = calloc(MAX_DEG, 8);
        p = (p + 1);
    }
    int64_t* tmp = (int64_t*)(calloc(MAX_DEG, 8));
    int32_t* len_out = (int32_t*)(calloc(1, 4));
    int32_t* ways_len = (int32_t*)(calloc(51, 4));
    ways[0][0] = 1;
    ways_len[0] = 1;
    p = 1;
    while (p <= (2 * MAX_TERMS)) {
        convolve_small_ptr_i64_i32_i32_ptr_i64_ptr_i32(ways[(p - 1)], ways_len[(p - 1)], 10, ways[p], len_out);
        ways_len[p] = len_out[0];
        p = (p + 1);
    }
    p = 0;
    while (p <= (2 * MAX_TERMS)) {
        memcpy((sum_tables + st_idx_i32_i32_i32(p, 0, 0)), ways[p], (((int64_t)(ways_len[p])) * 8));
        sum_table_len[stl_idx_i32_i32(p, 0)] = ways_len[p];
        int32_t q = 1;
        while (q <= (2 * MAX_TERMS)) {
            convolve_small_ptr_i64_i32_i32_ptr_i64_ptr_i32((sum_tables + st_idx_i32_i32_i32(p, (q - 1), 0)), sum_table_len[stl_idx_i32_i32(p, (q - 1))], 9, (sum_tables + st_idx_i32_i32_i32(p, q, 0)), len_out);
            sum_table_len[stl_idx_i32_i32(p, q)] = len_out[0];
            q = (q + 1);
        }
        p = (p + 1);
    }
    int64_t** trans_data = (int64_t**)(((int64_t**)(calloc(((26 * 26) * 51), 8))));
    int32_t* trans_count_arr = (int32_t*)(calloc(((26 * 26) * 51), 4));
    int8_t* trans_computed_arr = (int8_t*)(calloc(((26 * 26) * 51), 1));
    int64_t* dp = (int64_t*)(calloc((((51 * 26) * 26) * 51), 8));
    int32_t limit = MAX_N;
    int32_t lt = 1;
    while (lt <= MAX_TERMS) {
        int32_t rt = 1;
        while (rt <= MAX_TERMS) {
            int32_t base_length = ((lt + rt) - 1);
            if (base_length <= limit) {
                int64_t idx = dp_idx_i32_i32_i32_i32(base_length, lt, rt, MAX_CARRY);
                dp[idx] = mod_add_i64_i64(dp[idx], 1);
            }
            rt = (rt + 1);
        }
        lt = (lt + 1);
    }
    int64_t answer = 0;
    int32_t used = 0;
    while (used <= limit) {
        answer = mod_add_i64_i64(answer, dp[dp_idx_i32_i32_i32_i32(used, 0, 0, MAX_CARRY)]);
        int32_t al = 0;
        while (al <= MAX_TERMS) {
            int32_t ar = 0;
            while (ar <= MAX_TERMS) {
                if ((al == 0 && ar == 0)) {
                    ar = (ar + 1);
                    continue;
                }
                int32_t ci = 0;
                while (ci < CARRY_RANGE) {
                    int64_t ways_val = dp[dp_idx_i32_i32_i32_i32(used, al, ar, ci)];
                    if (ways_val == 0) {
                        ci = (ci + 1);
                        continue;
                    }
                    int32_t carry = (ci - MAX_CARRY);
                    int64_t tidx = trans_idx_i32_i32_i32(al, ar, ci);
                    if (trans_computed_arr[tidx] == 0) {
                        trans_computed_arr[tidx] = 1;
                        if ((al == 0 && ar == 0)) {
                            trans_count_arr[tidx] = 0;
                        } else {
                            int32_t count = 0;
                            int32_t nl = 0;
                            while (nl <= al) {
                                int32_t nr = 0;
                                while (nr <= ar) {
                                    int32_t continuing = (nl + nr);
                                    int32_t ending = ((al - nl) + (ar - nr));
                                    int32_t ending_left = (al - nl);
                                    int64_t* counts = (int64_t*)((sum_tables + st_idx_i32_i32_i32(continuing, ending, 0)));
                                    int32_t clen = sum_table_len[stl_idx_i32_i32(continuing, ending)];
                                    int64_t base = (((-((int64_t)(carry))) - ((int64_t)(ending_left))) + (9 * ((int64_t)(ar))));
                                    int32_t nc = (-MAX_CARRY);
                                    while (nc <= MAX_CARRY) {
                                        int64_t index = ((10 * ((int64_t)(nc))) + base);
                                        if (((index >= 0 && index < ((int64_t)(clen))) && counts[index] != 0)) {
                                            count = (count + 1);
                                        }
                                        nc = (nc + 1);
                                    }
                                    nr = (nr + 1);
                                }
                                nl = (nl + 1);
                            }
                            trans_count_arr[tidx] = count;
                            if (count > 0) {
                                int64_t* list = (int64_t*)(calloc((((int64_t)(count)) * 4), 8));
                                int32_t idx2 = 0;
                                nl = 0;
                                while (nl <= al) {
                                    int64_t choose_left = binom[binom_idx_i32_i32(al, nl)];
                                    int32_t ending_left = (al - nl);
                                    int32_t nr = 0;
                                    while (nr <= ar) {
                                        int64_t choose_terms = mod_mul_i64_i64(choose_left, binom[binom_idx_i32_i32(ar, nr)]);
                                        int32_t continuing = (nl + nr);
                                        int32_t ending = (ending_left + (ar - nr));
                                        int64_t* counts = (int64_t*)((sum_tables + st_idx_i32_i32_i32(continuing, ending, 0)));
                                        int32_t clen = sum_table_len[stl_idx_i32_i32(continuing, ending)];
                                        int64_t base = (((-((int64_t)(carry))) - ((int64_t)(ending_left))) + (9 * ((int64_t)(ar))));
                                        int32_t nc = (-MAX_CARRY);
                                        while (nc <= MAX_CARRY) {
                                            int64_t index = ((10 * ((int64_t)(nc))) + base);
                                            if (((index >= 0 && index < ((int64_t)(clen))) && counts[index] != 0)) {
                                                int64_t weight = mod_mul_i64_i64(choose_terms, counts[index]);
                                                list[((((int64_t)(idx2)) * 4) + 0)] = ((int64_t)(nl));
                                                list[((((int64_t)(idx2)) * 4) + 1)] = ((int64_t)(nr));
                                                list[((((int64_t)(idx2)) * 4) + 2)] = ((int64_t)(nc));
                                                list[((((int64_t)(idx2)) * 4) + 3)] = weight;
                                                idx2 = (idx2 + 1);
                                            }
                                            nc = (nc + 1);
                                        }
                                        nr = (nr + 1);
                                    }
                                    nl = (nl + 1);
                                }
                                trans_data[tidx] = list;
                            }
                        }
                    }
                    int32_t cnt = trans_count_arr[tidx];
                    int32_t next_length = ((used + al) + ar);
                    if (next_length > limit) {
                        ci = (ci + 1);
                        continue;
                    }
                    int64_t* list = (int64_t*)(trans_data[tidx]);
                    int32_t t = 0;
                    while (t < cnt) {
                        int32_t nci = (((int32_t)(list[((((int64_t)(t)) * 4) + 2)])) + MAX_CARRY);
                        int64_t val = mod_mul_i64_i64(ways_val, list[((((int64_t)(t)) * 4) + 3)]);
                        int32_t nli = ((int32_t)(list[((((int64_t)(t)) * 4) + 0)]));
                        int32_t nri = ((int32_t)(list[((((int64_t)(t)) * 4) + 1)]));
                        int64_t di = dp_idx_i32_i32_i32_i32(next_length, nli, nri, nci);
                        dp[di] = mod_add_i64_i64(dp[di], val);
                        t = (t + 1);
                    }
                    ci = (ci + 1);
                }
                ar = (ar + 1);
            }
            al = (al + 1);
        }
        used = (used + 1);
    }
    printf("%lld\n", answer);
    p = 0;
    while (p <= 50) {
        free(((void*)(ways[p])));
        p = (p + 1);
    }
    free(((void*)(ways)));
    free(((void*)(tmp)));
    free(((void*)(len_out)));
    free(((void*)(ways_len)));
    free(((void*)(binom)));
    free(((void*)(sum_tables)));
    free(((void*)(sum_table_len)));
    int64_t ti = 0;
    while (ti < ((26 * 26) * 51)) {
        if (trans_data[ti] != NULL) {
            free(((void*)(trans_data[ti])));
        }
        ti = (ti + 1);
    }
    free(((void*)(trans_data)));
    free(((void*)(trans_count_arr)));
    free(((void*)(trans_computed_arr)));
    free(((void*)(dp)));
    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) -> ()
  func.func private @memset(!llvm.ptr, i32, i64) -> !llvm.ptr
  func.func private @memcpy(!llvm.ptr, !llvm.ptr, i64) -> !llvm.ptr
  // Constant: MOD
  llvm.mlir.global internal constant @MOD(1000000007 : i64) : i64
  // Constant: MAX_N
  llvm.mlir.global internal constant @MAX_N(50 : i32) : i32
  // Constant: MAX_TERMS
  llvm.mlir.global internal constant @MAX_TERMS(25 : i32) : i32
  // Constant: MAX_CARRY
  llvm.mlir.global internal constant @MAX_CARRY(25 : i32) : i32
  // Constant: CARRY_RANGE
  llvm.mlir.global internal constant @CARRY_RANGE(51 : i32) : i32
  // Constant: MAX_DEG
  llvm.mlir.global internal constant @MAX_DEG(851 : i32) : i32
  func.func @mod_add(%arg0: i64, %arg1: i64) -> i64 {
    %0 = arith.addi %arg0, %arg1 : i64
    %1 = llvm.mlir.constant(1 : i64) : i64
    %2 = llvm.alloca %1 x i64 : (i64) -> !llvm.ptr
    llvm.store %0, %2 : i64, !llvm.ptr
    %3 = llvm.load %2 : !llvm.ptr -> i64
    %4 = llvm.mlir.addressof @MOD : !llvm.ptr
    %5 = llvm.load %4 : !llvm.ptr -> i64
    %6 = arith.cmpi sge, %3, %5 : i64
    cf.cond_br %6, ^bb0, ^bb1
    ^bb0:
      %7 = llvm.load %2 : !llvm.ptr -> i64
      %8 = llvm.mlir.addressof @MOD : !llvm.ptr
      %9 = llvm.load %8 : !llvm.ptr -> i64
      %10 = arith.subi %7, %9 : i64
      llvm.store %10, %2 : i64, !llvm.ptr
      cf.br ^bb2
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %11 = llvm.load %2 : !llvm.ptr -> i64
    func.return %11 : i64
  }
  func.func @mod_mul(%arg0: i64, %arg1: i64) -> i64 {
    %12 = arith.extsi %arg0 : i64 to i128
    %13 = arith.extsi %arg1 : i64 to i128
    %15 = arith.trunci %12 : i128 to i64
    %16 = arith.trunci %13 : i128 to i64
    %14 = arith.muli %15, %16 : i64
    %17 = llvm.mlir.addressof @MOD : !llvm.ptr
    %18 = llvm.load %17 : !llvm.ptr -> i64
    %19 = arith.remsi %14, %18 : i64
    func.return %19 : i64
  }
  func.func @binom_idx(%arg0: i32, %arg1: i32) -> i64 {
    %20 = arith.extsi %arg0 : i32 to i64
    %21 = arith.constant 26 : i32
    %23 = arith.extsi %21 : i32 to i64
    %22 = arith.muli %20, %23 : i64
    %24 = arith.extsi %arg1 : i32 to i64
    %25 = arith.addi %22, %24 : i64
    func.return %25 : i64
  }
  func.func @st_idx(%arg0: i32, %arg1: i32, %arg2: i32) -> i64 {
    %26 = arith.extsi %arg0 : i32 to i64
    %27 = arith.constant 51 : i32
    %29 = arith.extsi %27 : i32 to i64
    %28 = arith.muli %26, %29 : i64
    %30 = arith.constant 851 : i32
    %32 = arith.extsi %30 : i32 to i64
    %31 = arith.muli %28, %32 : i64
    %33 = arith.extsi %arg1 : i32 to i64
    %34 = arith.constant 851 : i32
    %36 = arith.extsi %34 : i32 to i64
    %35 = arith.muli %33, %36 : i64
    %37 = arith.addi %31, %35 : i64
    %38 = arith.extsi %arg2 : i32 to i64
    %39 = arith.addi %37, %38 : i64
    func.return %39 : i64
  }
  func.func @stl_idx(%arg0: i32, %arg1: i32) -> i64 {
    %40 = arith.extsi %arg0 : i32 to i64
    %41 = arith.constant 51 : i32
    %43 = arith.extsi %41 : i32 to i64
    %42 = arith.muli %40, %43 : i64
    %44 = arith.extsi %arg1 : i32 to i64
    %45 = arith.addi %42, %44 : i64
    func.return %45 : i64
  }
  func.func @trans_idx(%arg0: i32, %arg1: i32, %arg2: i32) -> i64 {
    %46 = arith.extsi %arg0 : i32 to i64
    %47 = arith.constant 26 : i32
    %49 = arith.extsi %47 : i32 to i64
    %48 = arith.muli %46, %49 : i64
    %50 = arith.constant 51 : i32
    %52 = arith.extsi %50 : i32 to i64
    %51 = arith.muli %48, %52 : i64
    %53 = arith.extsi %arg1 : i32 to i64
    %54 = arith.constant 51 : i32
    %56 = arith.extsi %54 : i32 to i64
    %55 = arith.muli %53, %56 : i64
    %57 = arith.addi %51, %55 : i64
    %58 = arith.extsi %arg2 : i32 to i64
    %59 = arith.addi %57, %58 : i64
    func.return %59 : i64
  }
  func.func @dp_idx(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> i64 {
    %60 = arith.extsi %arg0 : i32 to i64
    %61 = arith.constant 26 : i32
    %63 = arith.extsi %61 : i32 to i64
    %62 = arith.muli %60, %63 : i64
    %64 = arith.constant 26 : i32
    %66 = arith.extsi %64 : i32 to i64
    %65 = arith.muli %62, %66 : i64
    %67 = arith.constant 51 : i32
    %69 = arith.extsi %67 : i32 to i64
    %68 = arith.muli %65, %69 : i64
    %70 = arith.extsi %arg1 : i32 to i64
    %71 = arith.constant 26 : i32
    %73 = arith.extsi %71 : i32 to i64
    %72 = arith.muli %70, %73 : i64
    %74 = arith.constant 51 : i32
    %76 = arith.extsi %74 : i32 to i64
    %75 = arith.muli %72, %76 : i64
    %77 = arith.addi %68, %75 : i64
    %78 = arith.extsi %arg2 : i32 to i64
    %79 = arith.constant 51 : i32
    %81 = arith.extsi %79 : i32 to i64
    %80 = arith.muli %78, %81 : i64
    %82 = arith.addi %77, %80 : i64
    %83 = arith.extsi %arg3 : i32 to i64
    %84 = arith.addi %82, %83 : i64
    func.return %84 : i64
  }
  func.func @convolve_small(%arg0: !llvm.ptr, %arg1: i32, %arg2: i32, %arg3: !llvm.ptr, %arg4: !llvm.ptr) -> () {
    %85 = arith.addi %arg1, %arg2 : i32
    %86 = arith.constant 1 : i32
    %87 = arith.subi %85, %86 : i32
    %88 = arith.constant 0 : i32
    %89 = llvm.mlir.constant(1 : i64) : i64
    %90 = llvm.alloca %89 x i32 : (i64) -> !llvm.ptr
    llvm.store %88, %90 : i32, !llvm.ptr
    cf.br ^bb3
    ^bb3:
    %91 = llvm.load %90 : !llvm.ptr -> i32
    %92 = arith.cmpi slt, %91, %87 : i32
    cf.cond_br %92, ^bb4, ^bb5
    ^bb4:
      %93 = arith.constant 0 : i32
      %94 = llvm.load %90 : !llvm.ptr -> i32
      %95 = arith.extsi %93 : i32 to i64
      %96 = arith.extsi %94 : i32 to i64
      %97 = llvm.getelementptr %arg3[%96] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %95, %97 : i64, !llvm.ptr
      %98 = llvm.load %90 : !llvm.ptr -> i32
      %99 = arith.constant 1 : i32
      %100 = arith.addi %98, %99 : i32
      llvm.store %100, %90 : i32, !llvm.ptr
      cf.br ^bb3
    ^bb5:
    %101 = arith.constant 0 : i32
    llvm.store %101, %90 : i32, !llvm.ptr
    cf.br ^bb6
    ^bb6:
    %102 = llvm.load %90 : !llvm.ptr -> i32
    %103 = arith.cmpi slt, %102, %arg1 : i32
    cf.cond_br %103, ^bb7, ^bb8
    ^bb7:
      %105 = llvm.load %90 : !llvm.ptr -> i32
      %106 = arith.extsi %105 : i32 to i64
      %107 = llvm.getelementptr %arg0[%106] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %104 = llvm.load %107 : !llvm.ptr -> i64
      %108 = arith.constant 0 : i32
      %110 = arith.extsi %108 : i32 to i64
      %109 = arith.cmpi ne, %104, %110 : i64
      cf.cond_br %109, ^bb9, ^bb10
      ^bb9:
        %111 = arith.constant 0 : i32
        %112 = llvm.mlir.constant(1 : i64) : i64
        %113 = llvm.alloca %112 x i32 : (i64) -> !llvm.ptr
        llvm.store %111, %113 : i32, !llvm.ptr
        cf.br ^bb12
        ^bb12:
        %114 = llvm.load %113 : !llvm.ptr -> i32
        %115 = arith.cmpi slt, %114, %arg2 : i32
        cf.cond_br %115, ^bb13, ^bb14
        ^bb13:
          %118 = llvm.load %90 : !llvm.ptr -> i32
          %119 = llvm.load %113 : !llvm.ptr -> i32
          %120 = arith.addi %118, %119 : i32
          %121 = arith.extsi %120 : i32 to i64
          %122 = llvm.getelementptr %arg3[%121] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %117 = llvm.load %122 : !llvm.ptr -> i64
          %124 = llvm.load %90 : !llvm.ptr -> i32
          %125 = arith.extsi %124 : i32 to i64
          %126 = llvm.getelementptr %arg0[%125] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %123 = llvm.load %126 : !llvm.ptr -> i64
          %116 = func.call @mod_add(%117, %123) : (i64, i64) -> i64
          %127 = llvm.load %90 : !llvm.ptr -> i32
          %128 = llvm.load %113 : !llvm.ptr -> i32
          %129 = arith.addi %127, %128 : i32
          %130 = arith.extsi %129 : i32 to i64
          %131 = llvm.getelementptr %arg3[%130] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %116, %131 : i64, !llvm.ptr
          %132 = llvm.load %113 : !llvm.ptr -> i32
          %133 = arith.constant 1 : i32
          %134 = arith.addi %132, %133 : i32
          llvm.store %134, %113 : i32, !llvm.ptr
          cf.br ^bb12
        ^bb14:
        cf.br ^bb11
      ^bb10:
        cf.br ^bb11
      ^bb11:
      %135 = llvm.load %90 : !llvm.ptr -> i32
      %136 = arith.constant 1 : i32
      %137 = arith.addi %135, %136 : i32
      llvm.store %137, %90 : i32, !llvm.ptr
      cf.br ^bb6
    ^bb8:
    %138 = arith.constant 0 : i32
    %139 = arith.extsi %138 : i32 to i64
    %140 = llvm.getelementptr %arg4[%139] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %87, %140 : i32, !llvm.ptr
    func.return
  }
  func.func @main() -> i32 {
    %142 = arith.constant 26 : i32
    %143 = arith.constant 26 : i32
    %144 = arith.muli %142, %143 : i32
    %145 = arith.constant 8 : i32
    %146 = arith.extsi %144 : i32 to i64
    %147 = arith.extsi %145 : i32 to i64
    %141 = func.call @calloc(%146, %147) : (i64, i64) -> !llvm.ptr
    %148 = arith.constant 0 : i32
    %149 = llvm.mlir.constant(1 : i64) : i64
    %150 = llvm.alloca %149 x i32 : (i64) -> !llvm.ptr
    llvm.store %148, %150 : i32, !llvm.ptr
    cf.br ^bb15
    ^bb15:
    %151 = llvm.load %150 : !llvm.ptr -> i32
    %152 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
    %153 = llvm.load %152 : !llvm.ptr -> i32
    %154 = arith.cmpi sle, %151, %153 : i32
    cf.cond_br %154, ^bb16, ^bb17
    ^bb16:
      %155 = arith.constant 1 : i32
      %157 = llvm.load %150 : !llvm.ptr -> i32
      %158 = arith.constant 0 : i32
      %156 = func.call @binom_idx(%157, %158) : (i32, i32) -> i64
      %159 = arith.extsi %155 : i32 to i64
      %160 = llvm.getelementptr %141[%156] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %159, %160 : i64, !llvm.ptr
      %161 = arith.constant 1 : i32
      %163 = llvm.load %150 : !llvm.ptr -> i32
      %164 = llvm.load %150 : !llvm.ptr -> i32
      %162 = func.call @binom_idx(%163, %164) : (i32, i32) -> i64
      %165 = arith.extsi %161 : i32 to i64
      %166 = llvm.getelementptr %141[%162] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      llvm.store %165, %166 : i64, !llvm.ptr
      %167 = arith.constant 1 : i32
      %168 = llvm.mlir.constant(1 : i64) : i64
      %169 = llvm.alloca %168 x i32 : (i64) -> !llvm.ptr
      llvm.store %167, %169 : i32, !llvm.ptr
      cf.br ^bb18
      ^bb18:
      %170 = llvm.load %169 : !llvm.ptr -> i32
      %171 = llvm.load %150 : !llvm.ptr -> i32
      %172 = arith.cmpi slt, %170, %171 : i32
      cf.cond_br %172, ^bb19, ^bb20
      ^bb19:
        %176 = llvm.load %150 : !llvm.ptr -> i32
        %177 = arith.constant 1 : i32
        %178 = arith.subi %176, %177 : i32
        %179 = llvm.load %169 : !llvm.ptr -> i32
        %180 = arith.constant 1 : i32
        %181 = arith.subi %179, %180 : i32
        %175 = func.call @binom_idx(%178, %181) : (i32, i32) -> i64
        %182 = llvm.getelementptr %141[%175] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %174 = llvm.load %182 : !llvm.ptr -> i64
        %185 = llvm.load %150 : !llvm.ptr -> i32
        %186 = arith.constant 1 : i32
        %187 = arith.subi %185, %186 : i32
        %188 = llvm.load %169 : !llvm.ptr -> i32
        %184 = func.call @binom_idx(%187, %188) : (i32, i32) -> i64
        %189 = llvm.getelementptr %141[%184] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        %183 = llvm.load %189 : !llvm.ptr -> i64
        %173 = func.call @mod_add(%174, %183) : (i64, i64) -> i64
        %191 = llvm.load %150 : !llvm.ptr -> i32
        %192 = llvm.load %169 : !llvm.ptr -> i32
        %190 = func.call @binom_idx(%191, %192) : (i32, i32) -> i64
        %193 = llvm.getelementptr %141[%190] : (!llvm.ptr, i64) -> !llvm.ptr, i64
        llvm.store %173, %193 : i64, !llvm.ptr
        %194 = llvm.load %169 : !llvm.ptr -> i32
        %195 = arith.constant 1 : i32
        %196 = arith.addi %194, %195 : i32
        llvm.store %196, %169 : i32, !llvm.ptr
        cf.br ^bb18
      ^bb20:
      %197 = llvm.load %150 : !llvm.ptr -> i32
      %198 = arith.constant 1 : i32
      %199 = arith.addi %197, %198 : i32
      llvm.store %199, %150 : i32, !llvm.ptr
      cf.br ^bb15
    ^bb17:
    %201 = arith.constant 51 : i32
    %202 = arith.constant 51 : i32
    %203 = arith.muli %201, %202 : i32
    %204 = arith.constant 851 : i32
    %205 = arith.muli %203, %204 : i32
    %206 = arith.constant 8 : i32
    %207 = arith.extsi %205 : i32 to i64
    %208 = arith.extsi %206 : i32 to i64
    %200 = func.call @calloc(%207, %208) : (i64, i64) -> !llvm.ptr
    %210 = arith.constant 51 : i32
    %211 = arith.constant 51 : i32
    %212 = arith.muli %210, %211 : i32
    %213 = arith.constant 4 : i32
    %214 = arith.extsi %212 : i32 to i64
    %215 = arith.extsi %213 : i32 to i64
    %209 = func.call @calloc(%214, %215) : (i64, i64) -> !llvm.ptr
    %217 = arith.constant 51 : i32
    %218 = arith.constant 8 : i32
    %219 = arith.extsi %217 : i32 to i64
    %220 = arith.extsi %218 : i32 to i64
    %216 = func.call @calloc(%219, %220) : (i64, i64) -> !llvm.ptr
    %221 = arith.constant 0 : i32
    %222 = llvm.mlir.constant(1 : i64) : i64
    %223 = llvm.alloca %222 x i32 : (i64) -> !llvm.ptr
    llvm.store %221, %223 : i32, !llvm.ptr
    cf.br ^bb21
    ^bb21:
    %224 = llvm.load %223 : !llvm.ptr -> i32
    %225 = arith.constant 50 : i32
    %226 = arith.cmpi sle, %224, %225 : i32
    cf.cond_br %226, ^bb22, ^bb23
    ^bb22:
      %228 = llvm.mlir.addressof @MAX_DEG : !llvm.ptr
      %229 = llvm.load %228 : !llvm.ptr -> i32
      %230 = arith.constant 8 : i32
      %231 = arith.extsi %229 : i32 to i64
      %232 = arith.extsi %230 : i32 to i64
      %227 = func.call @calloc(%231, %232) : (i64, i64) -> !llvm.ptr
      %233 = llvm.load %223 : !llvm.ptr -> i32
      %234 = arith.extsi %233 : i32 to i64
      %235 = llvm.getelementptr %216[%234] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      llvm.store %227, %235 : !llvm.ptr, !llvm.ptr
      %236 = llvm.load %223 : !llvm.ptr -> i32
      %237 = arith.constant 1 : i32
      %238 = arith.addi %236, %237 : i32
      llvm.store %238, %223 : i32, !llvm.ptr
      cf.br ^bb21
    ^bb23:
    %240 = llvm.mlir.addressof @MAX_DEG : !llvm.ptr
    %241 = llvm.load %240 : !llvm.ptr -> i32
    %242 = arith.constant 8 : i32
    %243 = arith.extsi %241 : i32 to i64
    %244 = arith.extsi %242 : i32 to i64
    %239 = func.call @calloc(%243, %244) : (i64, i64) -> !llvm.ptr
    %246 = arith.constant 1 : i32
    %247 = arith.constant 4 : i32
    %248 = arith.extsi %246 : i32 to i64
    %249 = arith.extsi %247 : i32 to i64
    %245 = func.call @calloc(%248, %249) : (i64, i64) -> !llvm.ptr
    %251 = arith.constant 51 : i32
    %252 = arith.constant 4 : i32
    %253 = arith.extsi %251 : i32 to i64
    %254 = arith.extsi %252 : i32 to i64
    %250 = func.call @calloc(%253, %254) : (i64, i64) -> !llvm.ptr
    %255 = arith.constant 1 : i32
    %257 = arith.constant 0 : i32
    %258 = arith.extsi %257 : i32 to i64
    %259 = llvm.getelementptr %216[%258] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
    %256 = llvm.load %259 : !llvm.ptr -> !llvm.ptr
    %260 = arith.constant 0 : i32
    %261 = arith.extsi %255 : i32 to i64
    %262 = arith.extsi %260 : i32 to i64
    %263 = llvm.getelementptr %256[%262] : (!llvm.ptr, i64) -> !llvm.ptr, i64
    llvm.store %261, %263 : i64, !llvm.ptr
    %264 = arith.constant 1 : i32
    %265 = arith.constant 0 : i32
    %266 = arith.extsi %265 : i32 to i64
    %267 = llvm.getelementptr %250[%266] : (!llvm.ptr, i64) -> !llvm.ptr, i32
    llvm.store %264, %267 : i32, !llvm.ptr
    %268 = arith.constant 1 : i32
    llvm.store %268, %223 : i32, !llvm.ptr
    cf.br ^bb24
    ^bb24:
    %269 = llvm.load %223 : !llvm.ptr -> i32
    %270 = arith.constant 2 : i32
    %271 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
    %272 = llvm.load %271 : !llvm.ptr -> i32
    %273 = arith.muli %270, %272 : i32
    %274 = arith.cmpi sle, %269, %273 : i32
    cf.cond_br %274, ^bb25, ^bb26
    ^bb25:
      %277 = llvm.load %223 : !llvm.ptr -> i32
      %278 = arith.constant 1 : i32
      %279 = arith.subi %277, %278 : i32
      %280 = arith.extsi %279 : i32 to i64
      %281 = llvm.getelementptr %216[%280] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %276 = llvm.load %281 : !llvm.ptr -> !llvm.ptr
      %283 = llvm.load %223 : !llvm.ptr -> i32
      %284 = arith.constant 1 : i32
      %285 = arith.subi %283, %284 : i32
      %286 = arith.extsi %285 : i32 to i64
      %287 = llvm.getelementptr %250[%286] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %282 = llvm.load %287 : !llvm.ptr -> i32
      %288 = arith.constant 10 : i32
      %290 = llvm.load %223 : !llvm.ptr -> i32
      %291 = arith.extsi %290 : i32 to i64
      %292 = llvm.getelementptr %216[%291] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %289 = llvm.load %292 : !llvm.ptr -> !llvm.ptr
      func.call @convolve_small(%276, %282, %288, %289, %245) : (!llvm.ptr, i32, i32, !llvm.ptr, !llvm.ptr) -> ()
      %294 = arith.constant 0 : i32
      %295 = arith.extsi %294 : i32 to i64
      %296 = llvm.getelementptr %245[%295] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %293 = llvm.load %296 : !llvm.ptr -> i32
      %297 = llvm.load %223 : !llvm.ptr -> i32
      %298 = arith.extsi %297 : i32 to i64
      %299 = llvm.getelementptr %250[%298] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %293, %299 : i32, !llvm.ptr
      %300 = llvm.load %223 : !llvm.ptr -> i32
      %301 = arith.constant 1 : i32
      %302 = arith.addi %300, %301 : i32
      llvm.store %302, %223 : i32, !llvm.ptr
      cf.br ^bb24
    ^bb26:
    %303 = arith.constant 0 : i32
    llvm.store %303, %223 : i32, !llvm.ptr
    cf.br ^bb27
    ^bb27:
    %304 = llvm.load %223 : !llvm.ptr -> i32
    %305 = arith.constant 2 : i32
    %306 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
    %307 = llvm.load %306 : !llvm.ptr -> i32
    %308 = arith.muli %305, %307 : i32
    %309 = arith.cmpi sle, %304, %308 : i32
    cf.cond_br %309, ^bb28, ^bb29
    ^bb28:
      # String concatenation: !llvm.ptr + i64
      %313 = llvm.load %223 : !llvm.ptr -> i32
      %314 = arith.extsi %313 : i32 to i64
      %315 = llvm.getelementptr %216[%314] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %312 = llvm.load %315 : !llvm.ptr -> !llvm.ptr
      %317 = llvm.load %223 : !llvm.ptr -> i32
      %318 = arith.extsi %317 : i32 to i64
      %319 = llvm.getelementptr %250[%318] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %316 = llvm.load %319 : !llvm.ptr -> i32
      %320 = arith.extsi %316 : i32 to i64
      %321 = arith.constant 8 : i32
      %323 = arith.extsi %321 : i32 to i64
      %322 = arith.muli %320, %323 : i64
      %310 = func.call @memcpy(%311, %312, %322) : (!llvm.ptr, !llvm.ptr, i64) -> !llvm.ptr
      %325 = llvm.load %223 : !llvm.ptr -> i32
      %326 = arith.extsi %325 : i32 to i64
      %327 = llvm.getelementptr %250[%326] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      %324 = llvm.load %327 : !llvm.ptr -> i32
      %329 = llvm.load %223 : !llvm.ptr -> i32
      %330 = arith.constant 0 : i32
      %328 = func.call @stl_idx(%329, %330) : (i32, i32) -> i64
      %331 = llvm.getelementptr %209[%328] : (!llvm.ptr, i64) -> !llvm.ptr, i32
      llvm.store %324, %331 : i32, !llvm.ptr
      %332 = arith.constant 1 : i32
      %333 = llvm.mlir.constant(1 : i64) : i64
      %334 = llvm.alloca %333 x i32 : (i64) -> !llvm.ptr
      llvm.store %332, %334 : i32, !llvm.ptr
      cf.br ^bb30
      ^bb30:
      %335 = llvm.load %334 : !llvm.ptr -> i32
      %336 = arith.constant 2 : i32
      %337 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
      %338 = llvm.load %337 : !llvm.ptr -> i32
      %339 = arith.muli %336, %338 : i32
      %340 = arith.cmpi sle, %335, %339 : i32
      cf.cond_br %340, ^bb31, ^bb32
      ^bb31:
        # String concatenation: !llvm.ptr + i64
        %345 = llvm.load %223 : !llvm.ptr -> i32
        %346 = llvm.load %334 : !llvm.ptr -> i32
        %347 = arith.constant 1 : i32
        %348 = arith.subi %346, %347 : i32
        %344 = func.call @stl_idx(%345, %348) : (i32, i32) -> i64
        %349 = llvm.getelementptr %209[%344] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %343 = llvm.load %349 : !llvm.ptr -> i32
        %350 = arith.constant 9 : i32
        # String concatenation: !llvm.ptr + i64
        func.call @convolve_small(%342, %343, %350, %351, %245) : (!llvm.ptr, i32, i32, !llvm.ptr, !llvm.ptr) -> ()
        %353 = arith.constant 0 : i32
        %354 = arith.extsi %353 : i32 to i64
        %355 = llvm.getelementptr %245[%354] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        %352 = llvm.load %355 : !llvm.ptr -> i32
        %357 = llvm.load %223 : !llvm.ptr -> i32
        %358 = llvm.load %334 : !llvm.ptr -> i32
        %356 = func.call @stl_idx(%357, %358) : (i32, i32) -> i64
        %359 = llvm.getelementptr %209[%356] : (!llvm.ptr, i64) -> !llvm.ptr, i32
        llvm.store %352, %359 : i32, !llvm.ptr
        %360 = llvm.load %334 : !llvm.ptr -> i32
        %361 = arith.constant 1 : i32
        %362 = arith.addi %360, %361 : i32
        llvm.store %362, %334 : i32, !llvm.ptr
        cf.br ^bb30
      ^bb32:
      %363 = llvm.load %223 : !llvm.ptr -> i32
      %364 = arith.constant 1 : i32
      %365 = arith.addi %363, %364 : i32
      llvm.store %365, %223 : i32, !llvm.ptr
      cf.br ^bb27
    ^bb29:
    %367 = arith.constant 26 : i32
    %368 = arith.constant 26 : i32
    %369 = arith.muli %367, %368 : i32
    %370 = arith.constant 51 : i32
    %371 = arith.muli %369, %370 : i32
    %372 = arith.constant 8 : i32
    %373 = arith.extsi %371 : i32 to i64
    %374 = arith.extsi %372 : i32 to i64
    %366 = func.call @calloc(%373, %374) : (i64, i64) -> !llvm.ptr
    %376 = arith.constant 26 : i32
    %377 = arith.constant 26 : i32
    %378 = arith.muli %376, %377 : i32
    %379 = arith.constant 51 : i32
    %380 = arith.muli %378, %379 : i32
    %381 = arith.constant 4 : i32
    %382 = arith.extsi %380 : i32 to i64
    %383 = arith.extsi %381 : i32 to i64
    %375 = func.call @calloc(%382, %383) : (i64, i64) -> !llvm.ptr
    %385 = arith.constant 26 : i32
    %386 = arith.constant 26 : i32
    %387 = arith.muli %385, %386 : i32
    %388 = arith.constant 51 : i32
    %389 = arith.muli %387, %388 : i32
    %390 = arith.constant 1 : i32
    %391 = arith.extsi %389 : i32 to i64
    %392 = arith.extsi %390 : i32 to i64
    %384 = func.call @calloc(%391, %392) : (i64, i64) -> !llvm.ptr
    %394 = arith.constant 51 : i32
    %395 = arith.constant 26 : i32
    %396 = arith.muli %394, %395 : i32
    %397 = arith.constant 26 : i32
    %398 = arith.muli %396, %397 : i32
    %399 = arith.constant 51 : i32
    %400 = arith.muli %398, %399 : i32
    %401 = arith.constant 8 : i32
    %402 = arith.extsi %400 : i32 to i64
    %403 = arith.extsi %401 : i32 to i64
    %393 = func.call @calloc(%402, %403) : (i64, i64) -> !llvm.ptr
    %404 = llvm.mlir.addressof @MAX_N : !llvm.ptr
    %405 = llvm.load %404 : !llvm.ptr -> i32
    %406 = arith.constant 1 : i32
    %407 = llvm.mlir.constant(1 : i64) : i64
    %408 = llvm.alloca %407 x i32 : (i64) -> !llvm.ptr
    llvm.store %406, %408 : i32, !llvm.ptr
    cf.br ^bb33
    ^bb33:
    %409 = llvm.load %408 : !llvm.ptr -> i32
    %410 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
    %411 = llvm.load %410 : !llvm.ptr -> i32
    %412 = arith.cmpi sle, %409, %411 : i32
    cf.cond_br %412, ^bb34, ^bb35
    ^bb34:
      %413 = arith.constant 1 : i32
      %414 = llvm.mlir.constant(1 : i64) : i64
      %415 = llvm.alloca %414 x i32 : (i64) -> !llvm.ptr
      llvm.store %413, %415 : i32, !llvm.ptr
      cf.br ^bb36
      ^bb36:
      %416 = llvm.load %415 : !llvm.ptr -> i32
      %417 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
      %418 = llvm.load %417 : !llvm.ptr -> i32
      %419 = arith.cmpi sle, %416, %418 : i32
      cf.cond_br %419, ^bb37, ^bb38
      ^bb37:
        %420 = llvm.load %408 : !llvm.ptr -> i32
        %421 = llvm.load %415 : !llvm.ptr -> i32
        %422 = arith.addi %420, %421 : i32
        %423 = arith.constant 1 : i32
        %424 = arith.subi %422, %423 : i32
        %425 = arith.cmpi sle, %424, %405 : i32
        cf.cond_br %425, ^bb39, ^bb40
        ^bb39:
          %427 = llvm.load %408 : !llvm.ptr -> i32
          %428 = llvm.load %415 : !llvm.ptr -> i32
          %429 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
          %430 = llvm.load %429 : !llvm.ptr -> i32
          %426 = func.call @dp_idx(%424, %427, %428, %430) : (i32, i32, i32, i32) -> i64
          %433 = llvm.getelementptr %393[%426] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          %432 = llvm.load %433 : !llvm.ptr -> i64
          %434 = arith.constant 1 : i32
          %435 = arith.extsi %434 : i32 to i64
          %431 = func.call @mod_add(%432, %435) : (i64, i64) -> i64
          %436 = llvm.getelementptr %393[%426] : (!llvm.ptr, i64) -> !llvm.ptr, i64
          llvm.store %431, %436 : i64, !llvm.ptr
          cf.br ^bb41
        ^bb40:
          cf.br ^bb41
        ^bb41:
        %437 = llvm.load %415 : !llvm.ptr -> i32
        %438 = arith.constant 1 : i32
        %439 = arith.addi %437, %438 : i32
        llvm.store %439, %415 : i32, !llvm.ptr
        cf.br ^bb36
      ^bb38:
      %440 = llvm.load %408 : !llvm.ptr -> i32
      %441 = arith.constant 1 : i32
      %442 = arith.addi %440, %441 : i32
      llvm.store %442, %408 : i32, !llvm.ptr
      cf.br ^bb33
    ^bb35:
    %443 = arith.constant 0 : i32
    %444 = arith.extsi %443 : i32 to i64
    %445 = llvm.mlir.constant(1 : i64) : i64
    %446 = llvm.alloca %445 x i64 : (i64) -> !llvm.ptr
    llvm.store %444, %446 : i64, !llvm.ptr
    %447 = arith.constant 0 : i32
    %448 = llvm.mlir.constant(1 : i64) : i64
    %449 = llvm.alloca %448 x i32 : (i64) -> !llvm.ptr
    llvm.store %447, %449 : i32, !llvm.ptr
    cf.br ^bb42
    ^bb42:
    %450 = llvm.load %449 : !llvm.ptr -> i32
    %451 = arith.cmpi sle, %450, %405 : i32
    cf.cond_br %451, ^bb43, ^bb44
    ^bb43:
      %453 = llvm.load %446 : !llvm.ptr -> i64
      %456 = llvm.load %449 : !llvm.ptr -> i32
      %457 = arith.constant 0 : i32
      %458 = arith.constant 0 : i32
      %459 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
      %460 = llvm.load %459 : !llvm.ptr -> i32
      %455 = func.call @dp_idx(%456, %457, %458, %460) : (i32, i32, i32, i32) -> i64
      %461 = llvm.getelementptr %393[%455] : (!llvm.ptr, i64) -> !llvm.ptr, i64
      %454 = llvm.load %461 : !llvm.ptr -> i64
      %452 = func.call @mod_add(%453, %454) : (i64, i64) -> i64
      llvm.store %452, %446 : i64, !llvm.ptr
      %462 = arith.constant 0 : i32
      %463 = llvm.mlir.constant(1 : i64) : i64
      %464 = llvm.alloca %463 x i32 : (i64) -> !llvm.ptr
      llvm.store %462, %464 : i32, !llvm.ptr
      cf.br ^bb45
      ^bb45:
      %465 = llvm.load %464 : !llvm.ptr -> i32
      %466 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
      %467 = llvm.load %466 : !llvm.ptr -> i32
      %468 = arith.cmpi sle, %465, %467 : i32
      cf.cond_br %468, ^bb46, ^bb47
      ^bb46:
        %469 = arith.constant 0 : i32
        %470 = llvm.mlir.constant(1 : i64) : i64
        %471 = llvm.alloca %470 x i32 : (i64) -> !llvm.ptr
        llvm.store %469, %471 : i32, !llvm.ptr
        cf.br ^bb48
        ^bb48:
        %472 = llvm.load %471 : !llvm.ptr -> i32
        %473 = llvm.mlir.addressof @MAX_TERMS : !llvm.ptr
        %474 = llvm.load %473 : !llvm.ptr -> i32
        %475 = arith.cmpi sle, %472, %474 : i32
        cf.cond_br %475, ^bb49, ^bb50
        ^bb49:
          %476 = llvm.load %464 : !llvm.ptr -> i32
          %477 = arith.constant 0 : i32
          %478 = arith.cmpi eq, %476, %477 : i32
          %479 = scf.if %478 -> (i1) {
            %480 = llvm.load %471 : !llvm.ptr -> i32
            %481 = arith.constant 0 : i32
            %482 = arith.cmpi eq, %480, %481 : i32
            scf.yield %482 : i1
          } else {
            %483 = arith.constant false
            scf.yield %483 : i1
          }
          cf.cond_br %479, ^bb51, ^bb52
          ^bb51:
            %484 = llvm.load %471 : !llvm.ptr -> i32
            %485 = arith.constant 1 : i32
            %486 = arith.addi %484, %485 : i32
            llvm.store %486, %471 : i32, !llvm.ptr
            cf.br ^bb48
          ^bb52:
            cf.br ^bb53
          ^bb53:
          %487 = arith.constant 0 : i32
          %488 = llvm.mlir.constant(1 : i64) : i64
          %489 = llvm.alloca %488 x i32 : (i64) -> !llvm.ptr
          llvm.store %487, %489 : i32, !llvm.ptr
          cf.br ^bb54
          ^bb54:
          %490 = llvm.load %489 : !llvm.ptr -> i32
          %491 = llvm.mlir.addressof @CARRY_RANGE : !llvm.ptr
          %492 = llvm.load %491 : !llvm.ptr -> i32
          %493 = arith.cmpi slt, %490, %492 : i32
          cf.cond_br %493, ^bb55, ^bb56
          ^bb55:
            %496 = llvm.load %449 : !llvm.ptr -> i32
            %497 = llvm.load %464 : !llvm.ptr -> i32
            %498 = llvm.load %471 : !llvm.ptr -> i32
            %499 = llvm.load %489 : !llvm.ptr -> i32
            %495 = func.call @dp_idx(%496, %497, %498, %499) : (i32, i32, i32, i32) -> i64
            %500 = llvm.getelementptr %393[%495] : (!llvm.ptr, i64) -> !llvm.ptr, i64
            %494 = llvm.load %500 : !llvm.ptr -> i64
            %501 = arith.constant 0 : i32
            %503 = arith.extsi %501 : i32 to i64
            %502 = arith.cmpi eq, %494, %503 : i64
            cf.cond_br %502, ^bb57, ^bb58
            ^bb57:
              %504 = llvm.load %489 : !llvm.ptr -> i32
              %505 = arith.constant 1 : i32
              %506 = arith.addi %504, %505 : i32
              llvm.store %506, %489 : i32, !llvm.ptr
              cf.br ^bb54
            ^bb58:
              cf.br ^bb59
            ^bb59:
            %507 = llvm.load %489 : !llvm.ptr -> i32
            %508 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
            %509 = llvm.load %508 : !llvm.ptr -> i32
            %510 = arith.subi %507, %509 : i32
            %512 = llvm.load %464 : !llvm.ptr -> i32
            %513 = llvm.load %471 : !llvm.ptr -> i32
            %514 = llvm.load %489 : !llvm.ptr -> i32
            %511 = func.call @trans_idx(%512, %513, %514) : (i32, i32, i32) -> i64
            %516 = llvm.getelementptr %384[%511] : (!llvm.ptr, i64) -> !llvm.ptr, i8
            %515 = llvm.load %516 : !llvm.ptr -> i8
            %517 = arith.constant 0 : i32
            %519 = arith.extsi %515 : i8 to i32
            %518 = arith.cmpi eq, %519, %517 : i32
            cf.cond_br %518, ^bb60, ^bb61
            ^bb60:
              %520 = arith.constant 1 : i32
              %521 = arith.trunci %520 : i32 to i8
              %522 = llvm.getelementptr %384[%511] : (!llvm.ptr, i64) -> !llvm.ptr, i8
              llvm.store %521, %522 : i8, !llvm.ptr
              %523 = llvm.load %464 : !llvm.ptr -> i32
              %524 = arith.constant 0 : i32
              %525 = arith.cmpi eq, %523, %524 : i32
              %526 = scf.if %525 -> (i1) {
                %527 = llvm.load %471 : !llvm.ptr -> i32
                %528 = arith.constant 0 : i32
                %529 = arith.cmpi eq, %527, %528 : i32
                scf.yield %529 : i1
              } else {
                %530 = arith.constant false
                scf.yield %530 : i1
              }
              cf.cond_br %526, ^bb63, ^bb64
              ^bb63:
                %531 = arith.constant 0 : i32
                %532 = llvm.getelementptr %375[%511] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                llvm.store %531, %532 : i32, !llvm.ptr
                cf.br ^bb65
              ^bb64:
                %533 = arith.constant 0 : i32
                %534 = llvm.mlir.constant(1 : i64) : i64
                %535 = llvm.alloca %534 x i32 : (i64) -> !llvm.ptr
                llvm.store %533, %535 : i32, !llvm.ptr
                %536 = arith.constant 0 : i32
                %537 = llvm.mlir.constant(1 : i64) : i64
                %538 = llvm.alloca %537 x i32 : (i64) -> !llvm.ptr
                llvm.store %536, %538 : i32, !llvm.ptr
                cf.br ^bb66
                ^bb66:
                %539 = llvm.load %538 : !llvm.ptr -> i32
                %540 = llvm.load %464 : !llvm.ptr -> i32
                %541 = arith.cmpi sle, %539, %540 : i32
                cf.cond_br %541, ^bb67, ^bb68
                ^bb67:
                  %542 = arith.constant 0 : i32
                  %543 = llvm.mlir.constant(1 : i64) : i64
                  %544 = llvm.alloca %543 x i32 : (i64) -> !llvm.ptr
                  llvm.store %542, %544 : i32, !llvm.ptr
                  cf.br ^bb69
                  ^bb69:
                  %545 = llvm.load %544 : !llvm.ptr -> i32
                  %546 = llvm.load %471 : !llvm.ptr -> i32
                  %547 = arith.cmpi sle, %545, %546 : i32
                  cf.cond_br %547, ^bb70, ^bb71
                  ^bb70:
                    %548 = llvm.load %538 : !llvm.ptr -> i32
                    %549 = llvm.load %544 : !llvm.ptr -> i32
                    %550 = arith.addi %548, %549 : i32
                    %551 = llvm.load %464 : !llvm.ptr -> i32
                    %552 = llvm.load %538 : !llvm.ptr -> i32
                    %553 = arith.subi %551, %552 : i32
                    %554 = llvm.load %471 : !llvm.ptr -> i32
                    %555 = llvm.load %544 : !llvm.ptr -> i32
                    %556 = arith.subi %554, %555 : i32
                    %557 = arith.addi %553, %556 : i32
                    %558 = llvm.load %464 : !llvm.ptr -> i32
                    %559 = llvm.load %538 : !llvm.ptr -> i32
                    %560 = arith.subi %558, %559 : i32
                    # String concatenation: !llvm.ptr + i64
                    %563 = func.call @stl_idx(%550, %557) : (i32, i32) -> i64
                    %564 = llvm.getelementptr %209[%563] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                    %562 = llvm.load %564 : !llvm.ptr -> i32
                    %565 = arith.extsi %510 : i32 to i64
                    %567 = arith.constant 0 : i64
                    %566 = arith.subi %567, %565 : i64
                    %568 = arith.extsi %560 : i32 to i64
                    %569 = arith.subi %566, %568 : i64
                    %570 = arith.constant 9 : i32
                    %571 = llvm.load %471 : !llvm.ptr -> i32
                    %572 = arith.extsi %571 : i32 to i64
                    %574 = arith.extsi %570 : i32 to i64
                    %573 = arith.muli %574, %572 : i64
                    %575 = arith.addi %569, %573 : i64
                    %576 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
                    %577 = llvm.load %576 : !llvm.ptr -> i32
                    %579 = arith.constant 0 : i32
                    %578 = arith.subi %579, %577 : i32
                    %580 = llvm.mlir.constant(1 : i64) : i64
                    %581 = llvm.alloca %580 x i32 : (i64) -> !llvm.ptr
                    llvm.store %578, %581 : i32, !llvm.ptr
                    cf.br ^bb72
                    ^bb72:
                    %582 = llvm.load %581 : !llvm.ptr -> i32
                    %583 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
                    %584 = llvm.load %583 : !llvm.ptr -> i32
                    %585 = arith.cmpi sle, %582, %584 : i32
                    cf.cond_br %585, ^bb73, ^bb74
                    ^bb73:
                      %586 = arith.constant 10 : i32
                      %587 = llvm.load %581 : !llvm.ptr -> i32
                      %588 = arith.extsi %587 : i32 to i64
                      %590 = arith.extsi %586 : i32 to i64
                      %589 = arith.muli %590, %588 : i64
                      %591 = arith.addi %589, %575 : i64
                      %592 = arith.constant 0 : i32
                      %594 = arith.extsi %592 : i32 to i64
                      %593 = arith.cmpi sge, %591, %594 : i64
                      %595 = scf.if %593 -> (i1) {
                        %596 = arith.extsi %562 : i32 to i64
                        %597 = arith.cmpi slt, %591, %596 : i64
                        scf.yield %597 : i1
                      } else {
                        %598 = arith.constant false
                        scf.yield %598 : i1
                      }
                      %599 = scf.if %595 -> (i1) {
                        %601 = llvm.getelementptr %561[%591] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                        %600 = llvm.load %601 : !llvm.ptr -> i64
                        %602 = arith.constant 0 : i32
                        %604 = arith.extsi %602 : i32 to i64
                        %603 = arith.cmpi ne, %600, %604 : i64
                        scf.yield %603 : i1
                      } else {
                        %605 = arith.constant false
                        scf.yield %605 : i1
                      }
                      cf.cond_br %599, ^bb75, ^bb76
                      ^bb75:
                        %606 = llvm.load %535 : !llvm.ptr -> i32
                        %607 = arith.constant 1 : i32
                        %608 = arith.addi %606, %607 : i32
                        llvm.store %608, %535 : i32, !llvm.ptr
                        cf.br ^bb77
                      ^bb76:
                        cf.br ^bb77
                      ^bb77:
                      %609 = llvm.load %581 : !llvm.ptr -> i32
                      %610 = arith.constant 1 : i32
                      %611 = arith.addi %609, %610 : i32
                      llvm.store %611, %581 : i32, !llvm.ptr
                      cf.br ^bb72
                    ^bb74:
                    %612 = llvm.load %544 : !llvm.ptr -> i32
                    %613 = arith.constant 1 : i32
                    %614 = arith.addi %612, %613 : i32
                    llvm.store %614, %544 : i32, !llvm.ptr
                    cf.br ^bb69
                  ^bb71:
                  %615 = llvm.load %538 : !llvm.ptr -> i32
                  %616 = arith.constant 1 : i32
                  %617 = arith.addi %615, %616 : i32
                  llvm.store %617, %538 : i32, !llvm.ptr
                  cf.br ^bb66
                ^bb68:
                %618 = llvm.load %535 : !llvm.ptr -> i32
                %619 = llvm.getelementptr %375[%511] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                llvm.store %618, %619 : i32, !llvm.ptr
                %620 = llvm.load %535 : !llvm.ptr -> i32
                %621 = arith.constant 0 : i32
                %622 = arith.cmpi sgt, %620, %621 : i32
                cf.cond_br %622, ^bb78, ^bb79
                ^bb78:
                  %624 = llvm.load %535 : !llvm.ptr -> i32
                  %625 = arith.extsi %624 : i32 to i64
                  %626 = arith.constant 4 : i32
                  %628 = arith.extsi %626 : i32 to i64
                  %627 = arith.muli %625, %628 : i64
                  %629 = arith.constant 8 : i32
                  %630 = arith.extsi %629 : i32 to i64
                  %623 = func.call @calloc(%627, %630) : (i64, i64) -> !llvm.ptr
                  %631 = arith.constant 0 : i32
                  %632 = llvm.mlir.constant(1 : i64) : i64
                  %633 = llvm.alloca %632 x i32 : (i64) -> !llvm.ptr
                  llvm.store %631, %633 : i32, !llvm.ptr
                  %634 = arith.constant 0 : i32
                  llvm.store %634, %538 : i32, !llvm.ptr
                  cf.br ^bb81
                  ^bb81:
                  %635 = llvm.load %538 : !llvm.ptr -> i32
                  %636 = llvm.load %464 : !llvm.ptr -> i32
                  %637 = arith.cmpi sle, %635, %636 : i32
                  cf.cond_br %637, ^bb82, ^bb83
                  ^bb82:
                    %640 = llvm.load %464 : !llvm.ptr -> i32
                    %641 = llvm.load %538 : !llvm.ptr -> i32
                    %639 = func.call @binom_idx(%640, %641) : (i32, i32) -> i64
                    %642 = llvm.getelementptr %141[%639] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                    %638 = llvm.load %642 : !llvm.ptr -> i64
                    %643 = llvm.load %464 : !llvm.ptr -> i32
                    %644 = llvm.load %538 : !llvm.ptr -> i32
                    %645 = arith.subi %643, %644 : i32
                    %646 = arith.constant 0 : i32
                    %647 = llvm.mlir.constant(1 : i64) : i64
                    %648 = llvm.alloca %647 x i32 : (i64) -> !llvm.ptr
                    llvm.store %646, %648 : i32, !llvm.ptr
                    cf.br ^bb84
                    ^bb84:
                    %649 = llvm.load %648 : !llvm.ptr -> i32
                    %650 = llvm.load %471 : !llvm.ptr -> i32
                    %651 = arith.cmpi sle, %649, %650 : i32
                    cf.cond_br %651, ^bb85, ^bb86
                    ^bb85:
                      %655 = llvm.load %471 : !llvm.ptr -> i32
                      %656 = llvm.load %648 : !llvm.ptr -> i32
                      %654 = func.call @binom_idx(%655, %656) : (i32, i32) -> i64
                      %657 = llvm.getelementptr %141[%654] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                      %653 = llvm.load %657 : !llvm.ptr -> i64
                      %652 = func.call @mod_mul(%638, %653) : (i64, i64) -> i64
                      %658 = llvm.load %538 : !llvm.ptr -> i32
                      %659 = llvm.load %648 : !llvm.ptr -> i32
                      %660 = arith.addi %658, %659 : i32
                      %661 = llvm.load %471 : !llvm.ptr -> i32
                      %662 = llvm.load %648 : !llvm.ptr -> i32
                      %663 = arith.subi %661, %662 : i32
                      %664 = arith.addi %645, %663 : i32
                      # String concatenation: !llvm.ptr + i64
                      %667 = func.call @stl_idx(%660, %664) : (i32, i32) -> i64
                      %668 = llvm.getelementptr %209[%667] : (!llvm.ptr, i64) -> !llvm.ptr, i32
                      %666 = llvm.load %668 : !llvm.ptr -> i32
                      %669 = arith.extsi %510 : i32 to i64
                      %671 = arith.constant 0 : i64
                      %670 = arith.subi %671, %669 : i64
                      %672 = arith.extsi %645 : i32 to i64
                      %673 = arith.subi %670, %672 : i64
                      %674 = arith.constant 9 : i32
                      %675 = llvm.load %471 : !llvm.ptr -> i32
                      %676 = arith.extsi %675 : i32 to i64
                      %678 = arith.extsi %674 : i32 to i64
                      %677 = arith.muli %678, %676 : i64
                      %679 = arith.addi %673, %677 : i64
                      %680 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
                      %681 = llvm.load %680 : !llvm.ptr -> i32
                      %683 = arith.constant 0 : i32
                      %682 = arith.subi %683, %681 : i32
                      %684 = llvm.mlir.constant(1 : i64) : i64
                      %685 = llvm.alloca %684 x i32 : (i64) -> !llvm.ptr
                      llvm.store %682, %685 : i32, !llvm.ptr
                      cf.br ^bb87
                      ^bb87:
                      %686 = llvm.load %685 : !llvm.ptr -> i32
                      %687 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
                      %688 = llvm.load %687 : !llvm.ptr -> i32
                      %689 = arith.cmpi sle, %686, %688 : i32
                      cf.cond_br %689, ^bb88, ^bb89
                      ^bb88:
                        %690 = arith.constant 10 : i32
                        %691 = llvm.load %685 : !llvm.ptr -> i32
                        %692 = arith.extsi %691 : i32 to i64
                        %694 = arith.extsi %690 : i32 to i64
                        %693 = arith.muli %694, %692 : i64
                        %695 = arith.addi %693, %679 : i64
                        %696 = arith.constant 0 : i32
                        %698 = arith.extsi %696 : i32 to i64
                        %697 = arith.cmpi sge, %695, %698 : i64
                        %699 = scf.if %697 -> (i1) {
                          %700 = arith.extsi %666 : i32 to i64
                          %701 = arith.cmpi slt, %695, %700 : i64
                          scf.yield %701 : i1
                        } else {
                          %702 = arith.constant false
                          scf.yield %702 : i1
                        }
                        %703 = scf.if %699 -> (i1) {
                          %705 = llvm.getelementptr %665[%695] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                          %704 = llvm.load %705 : !llvm.ptr -> i64
                          %706 = arith.constant 0 : i32
                          %708 = arith.extsi %706 : i32 to i64
                          %707 = arith.cmpi ne, %704, %708 : i64
                          scf.yield %707 : i1
                        } else {
                          %709 = arith.constant false
                          scf.yield %709 : i1
                        }
                        cf.cond_br %703, ^bb90, ^bb91
                        ^bb90:
                          %712 = llvm.getelementptr %665[%695] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                          %711 = llvm.load %712 : !llvm.ptr -> i64
                          %710 = func.call @mod_mul(%652, %711) : (i64, i64) -> i64
                          %713 = llvm.load %538 : !llvm.ptr -> i32
                          %714 = arith.extsi %713 : i32 to i64
                          %715 = llvm.load %633 : !llvm.ptr -> i32
                          %716 = arith.extsi %715 : i32 to i64
                          %717 = arith.constant 4 : i32
                          %719 = arith.extsi %717 : i32 to i64
                          %718 = arith.muli %716, %719 : i64
                          %720 = arith.constant 0 : i32
                          %722 = arith.extsi %720 : i32 to i64
                          %721 = arith.addi %718, %722 : i64
                          %723 = llvm.getelementptr %623[%721] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                          llvm.store %714, %723 : i64, !llvm.ptr
                          %724 = llvm.load %648 : !llvm.ptr -> i32
                          %725 = arith.extsi %724 : i32 to i64
                          %726 = llvm.load %633 : !llvm.ptr -> i32
                          %727 = arith.extsi %726 : i32 to i64
                          %728 = arith.constant 4 : i32
                          %730 = arith.extsi %728 : i32 to i64
                          %729 = arith.muli %727, %730 : i64
                          %731 = arith.constant 1 : i32
                          %733 = arith.extsi %731 : i32 to i64
                          %732 = arith.addi %729, %733 : i64
                          %734 = llvm.getelementptr %623[%732] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                          llvm.store %725, %734 : i64, !llvm.ptr
                          %735 = llvm.load %685 : !llvm.ptr -> i32
                          %736 = arith.extsi %735 : i32 to i64
                          %737 = llvm.load %633 : !llvm.ptr -> i32
                          %738 = arith.extsi %737 : i32 to i64
                          %739 = arith.constant 4 : i32
                          %741 = arith.extsi %739 : i32 to i64
                          %740 = arith.muli %738, %741 : i64
                          %742 = arith.constant 2 : i32
                          %744 = arith.extsi %742 : i32 to i64
                          %743 = arith.addi %740, %744 : i64
                          %745 = llvm.getelementptr %623[%743] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                          llvm.store %736, %745 : i64, !llvm.ptr
                          %746 = llvm.load %633 : !llvm.ptr -> i32
                          %747 = arith.extsi %746 : i32 to i64
                          %748 = arith.constant 4 : i32
                          %750 = arith.extsi %748 : i32 to i64
                          %749 = arith.muli %747, %750 : i64
                          %751 = arith.constant 3 : i32
                          %753 = arith.extsi %751 : i32 to i64
                          %752 = arith.addi %749, %753 : i64
                          %754 = llvm.getelementptr %623[%752] : (!llvm.ptr, i64) -> !llvm.ptr, i64
                          llvm.store %710, %754 : i64, !llvm.ptr
                          %755 = llvm.load %633 : !llvm.ptr -> i32
                          %756 = arith.constant 1 : i32
                          %757 = arith.addi %755, %756 : i32
                          llvm.store %757, %633 : i32, !llvm.ptr
                          cf.br ^bb92
                        ^bb91:
                          cf.br ^bb92
                        ^bb92:
                        %758 = llvm.load %685 : !llvm.ptr -> i32
                        %759 = arith.constant 1 : i32
                        %760 = arith.addi %758, %759 : i32
                        llvm.store %760, %685 : i32, !llvm.ptr
                        cf.br ^bb87
                      ^bb89:
                      %761 = llvm.load %648 : !llvm.ptr -> i32
                      %762 = arith.constant 1 : i32
                      %763 = arith.addi %761, %762 : i32
                      llvm.store %763, %648 : i32, !llvm.ptr
                      cf.br ^bb84
                    ^bb86:
                    %764 = llvm.load %538 : !llvm.ptr -> i32
                    %765 = arith.constant 1 : i32
                    %766 = arith.addi %764, %765 : i32
                    llvm.store %766, %538 : i32, !llvm.ptr
                    cf.br ^bb81
                  ^bb83:
                  %767 = llvm.getelementptr %366[%511] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
                  llvm.store %623, %767 : !llvm.ptr, !llvm.ptr
                  cf.br ^bb80
                ^bb79:
                  cf.br ^bb80
                ^bb80:
                cf.br ^bb65
              ^bb65:
              cf.br ^bb62
            ^bb61:
              cf.br ^bb62
            ^bb62:
            %769 = llvm.getelementptr %375[%511] : (!llvm.ptr, i64) -> !llvm.ptr, i32
            %768 = llvm.load %769 : !llvm.ptr -> i32
            %770 = llvm.load %449 : !llvm.ptr -> i32
            %771 = llvm.load %464 : !llvm.ptr -> i32
            %772 = arith.addi %770, %771 : i32
            %773 = llvm.load %471 : !llvm.ptr -> i32
            %774 = arith.addi %772, %773 : i32
            %775 = arith.cmpi sgt, %774, %405 : i32
            cf.cond_br %775, ^bb93, ^bb94
            ^bb93:
              %776 = llvm.load %489 : !llvm.ptr -> i32
              %777 = arith.constant 1 : i32
              %778 = arith.addi %776, %777 : i32
              llvm.store %778, %489 : i32, !llvm.ptr
              cf.br ^bb54
            ^bb94:
              cf.br ^bb95
            ^bb95:
            %780 = llvm.getelementptr %366[%511] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
            %779 = llvm.load %780 : !llvm.ptr -> !llvm.ptr
            %781 = arith.constant 0 : i32
            %782 = llvm.mlir.constant(1 : i64) : i64
            %783 = llvm.alloca %782 x i32 : (i64) -> !llvm.ptr
            llvm.store %781, %783 : i32, !llvm.ptr
            cf.br ^bb96
            ^bb96:
            %784 = llvm.load %783 : !llvm.ptr -> i32
            %785 = arith.cmpi slt, %784, %768 : i32
            cf.cond_br %785, ^bb97, ^bb98
            ^bb97:
              %787 = llvm.load %783 : !llvm.ptr -> i32
              %788 = arith.extsi %787 : i32 to i64
              %789 = arith.constant 4 : i32
              %791 = arith.extsi %789 : i32 to i64
              %790 = arith.muli %788, %791 : i64
              %792 = arith.constant 2 : i32
              %794 = arith.extsi %792 : i32 to i64
              %793 = arith.addi %790, %794 : i64
              %795 = llvm.getelementptr %779[%793] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %786 = llvm.load %795 : !llvm.ptr -> i64
              %796 = arith.trunci %786 : i64 to i32
              %797 = llvm.mlir.addressof @MAX_CARRY : !llvm.ptr
              %798 = llvm.load %797 : !llvm.ptr -> i32
              %799 = arith.addi %796, %798 : i32
              %802 = llvm.load %783 : !llvm.ptr -> i32
              %803 = arith.extsi %802 : i32 to i64
              %804 = arith.constant 4 : i32
              %806 = arith.extsi %804 : i32 to i64
              %805 = arith.muli %803, %806 : i64
              %807 = arith.constant 3 : i32
              %809 = arith.extsi %807 : i32 to i64
              %808 = arith.addi %805, %809 : i64
              %810 = llvm.getelementptr %779[%808] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %801 = llvm.load %810 : !llvm.ptr -> i64
              %800 = func.call @mod_mul(%494, %801) : (i64, i64) -> i64
              %812 = llvm.load %783 : !llvm.ptr -> i32
              %813 = arith.extsi %812 : i32 to i64
              %814 = arith.constant 4 : i32
              %816 = arith.extsi %814 : i32 to i64
              %815 = arith.muli %813, %816 : i64
              %817 = arith.constant 0 : i32
              %819 = arith.extsi %817 : i32 to i64
              %818 = arith.addi %815, %819 : i64
              %820 = llvm.getelementptr %779[%818] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %811 = llvm.load %820 : !llvm.ptr -> i64
              %821 = arith.trunci %811 : i64 to i32
              %823 = llvm.load %783 : !llvm.ptr -> i32
              %824 = arith.extsi %823 : i32 to i64
              %825 = arith.constant 4 : i32
              %827 = arith.extsi %825 : i32 to i64
              %826 = arith.muli %824, %827 : i64
              %828 = arith.constant 1 : i32
              %830 = arith.extsi %828 : i32 to i64
              %829 = arith.addi %826, %830 : i64
              %831 = llvm.getelementptr %779[%829] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %822 = llvm.load %831 : !llvm.ptr -> i64
              %832 = arith.trunci %822 : i64 to i32
              %833 = func.call @dp_idx(%774, %821, %832, %799) : (i32, i32, i32, i32) -> i64
              %836 = llvm.getelementptr %393[%833] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              %835 = llvm.load %836 : !llvm.ptr -> i64
              %834 = func.call @mod_add(%835, %800) : (i64, i64) -> i64
              %837 = llvm.getelementptr %393[%833] : (!llvm.ptr, i64) -> !llvm.ptr, i64
              llvm.store %834, %837 : i64, !llvm.ptr
              %838 = llvm.load %783 : !llvm.ptr -> i32
              %839 = arith.constant 1 : i32
              %840 = arith.addi %838, %839 : i32
              llvm.store %840, %783 : i32, !llvm.ptr
              cf.br ^bb96
            ^bb98:
            %841 = llvm.load %489 : !llvm.ptr -> i32
            %842 = arith.constant 1 : i32
            %843 = arith.addi %841, %842 : i32
            llvm.store %843, %489 : i32, !llvm.ptr
            cf.br ^bb54
          ^bb56:
          %844 = llvm.load %471 : !llvm.ptr -> i32
          %845 = arith.constant 1 : i32
          %846 = arith.addi %844, %845 : i32
          llvm.store %846, %471 : i32, !llvm.ptr
          cf.br ^bb48
        ^bb50:
        %847 = llvm.load %464 : !llvm.ptr -> i32
        %848 = arith.constant 1 : i32
        %849 = arith.addi %847, %848 : i32
        llvm.store %849, %464 : i32, !llvm.ptr
        cf.br ^bb45
      ^bb47:
      %850 = llvm.load %449 : !llvm.ptr -> i32
      %851 = arith.constant 1 : i32
      %852 = arith.addi %850, %851 : i32
      llvm.store %852, %449 : i32, !llvm.ptr
      cf.br ^bb42
    ^bb44:
    %853 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %854 = llvm.load %446 : !llvm.ptr -> i64
    %855 = llvm.call @printf(%853, %854) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64) -> i32
    %856 = arith.constant 0 : i32
    llvm.store %856, %223 : i32, !llvm.ptr
    cf.br ^bb99
    ^bb99:
    %857 = llvm.load %223 : !llvm.ptr -> i32
    %858 = arith.constant 50 : i32
    %859 = arith.cmpi sle, %857, %858 : i32
    cf.cond_br %859, ^bb100, ^bb101
    ^bb100:
      %862 = llvm.load %223 : !llvm.ptr -> i32
      %863 = arith.extsi %862 : i32 to i64
      %864 = llvm.getelementptr %216[%863] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %861 = llvm.load %864 : !llvm.ptr -> !llvm.ptr
      func.call @free(%861) : (!llvm.ptr) -> ()
      %865 = llvm.load %223 : !llvm.ptr -> i32
      %866 = arith.constant 1 : i32
      %867 = arith.addi %865, %866 : i32
      llvm.store %867, %223 : i32, !llvm.ptr
      cf.br ^bb99
    ^bb101:
    func.call @free(%216) : (!llvm.ptr) -> ()
    func.call @free(%239) : (!llvm.ptr) -> ()
    func.call @free(%245) : (!llvm.ptr) -> ()
    func.call @free(%250) : (!llvm.ptr) -> ()
    func.call @free(%141) : (!llvm.ptr) -> ()
    func.call @free(%200) : (!llvm.ptr) -> ()
    func.call @free(%209) : (!llvm.ptr) -> ()
    %875 = arith.constant 0 : i32
    %876 = arith.extsi %875 : i32 to i64
    %877 = llvm.mlir.constant(1 : i64) : i64
    %878 = llvm.alloca %877 x i64 : (i64) -> !llvm.ptr
    llvm.store %876, %878 : i64, !llvm.ptr
    cf.br ^bb102
    ^bb102:
    %879 = llvm.load %878 : !llvm.ptr -> i64
    %880 = arith.constant 26 : i32
    %881 = arith.constant 26 : i32
    %882 = arith.muli %880, %881 : i32
    %883 = arith.constant 51 : i32
    %884 = arith.muli %882, %883 : i32
    %886 = arith.extsi %884 : i32 to i64
    %885 = arith.cmpi slt, %879, %886 : i64
    cf.cond_br %885, ^bb103, ^bb104
    ^bb103:
      %888 = llvm.load %878 : !llvm.ptr -> i64
      %889 = llvm.getelementptr %366[%888] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
      %887 = llvm.load %889 : !llvm.ptr -> !llvm.ptr
      %890 = llvm.mlir.zero : !llvm.ptr
      %891 = llvm.icmp "ne" %887, %890 : !llvm.ptr
      cf.cond_br %891, ^bb105, ^bb106
      ^bb105:
        %894 = llvm.load %878 : !llvm.ptr -> i64
        %895 = llvm.getelementptr %366[%894] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.ptr
        %893 = llvm.load %895 : !llvm.ptr -> !llvm.ptr
        func.call @free(%893) : (!llvm.ptr) -> ()
        cf.br ^bb107
      ^bb106:
        cf.br ^bb107
      ^bb107:
      %896 = llvm.load %878 : !llvm.ptr -> i64
      %897 = arith.constant 1 : i32
      %899 = arith.extsi %897 : i32 to i64
      %898 = arith.addi %896, %899 : i64
      llvm.store %898, %878 : i64, !llvm.ptr
      cf.br ^bb102
    ^bb104:
    func.call @free(%366) : (!llvm.ptr) -> ()
    func.call @free(%375) : (!llvm.ptr) -> ()
    func.call @free(%384) : (!llvm.ptr) -> ()
    func.call @free(%393) : (!llvm.ptr) -> ()
    %904 = arith.constant 0 : i32
    func.return %904 : i32
  }
}