| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| static const long long P = 998244353; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| struct State { |
| int instr; |
| int val; |
| }; |
|
|
| int main() { |
| long long targets[2] = {150994941LL, 150994939LL}; |
|
|
| for (int n = 8; n <= 27; n++) { |
| int d = n - 1; |
| |
| |
| |
|
|
| cerr << "n=" << n << " d=" << d << endl; |
|
|
| mt19937 rng(42 + n * 7777); |
| bool found[2] = {false, false}; |
|
|
| auto startTime = chrono::steady_clock::now(); |
| int timeLimit = (n <= 15) ? 15000 : (n <= 20) ? 10000 : 5000; |
|
|
| long long total_attempts = 0; |
|
|
| while (!(found[0] && found[1])) { |
| auto now = chrono::steady_clock::now(); |
| auto ms = chrono::duration_cast<chrono::milliseconds>(now - startTime).count(); |
| if (ms > timeLimit) break; |
|
|
| |
| int push_val[30], push_goto[30]; |
| int halt_push, halt_goto; |
| for (int i = 0; i < d; i++) { |
| push_val[i] = 1 + rng() % d; |
| push_goto[i] = rng() % (i + 1); |
| } |
| halt_push = 1 + rng() % d; |
| halt_goto = rng() % d; |
|
|
| |
| |
| |
| int maxVal = d; |
| int nstates = (d + 1) * (maxVal + 1); |
| vector<int> dest(nstates, -2); |
| vector<long long> cost(nstates, 0); |
| vector<int8_t> st(nstates, 0); |
| bool cycle = false; |
|
|
| function<pair<int,long long>(int,int)> solve = [&](int i, int x) -> pair<int,long long> { |
| int id = i * (maxVal + 1) + x; |
| if (st[id] == 2) return {dest[id], cost[id]}; |
| if (st[id] == 1) { cycle = true; return {-2, 0}; } |
| st[id] = 1; |
|
|
| int dd; long long cc; |
| if (i < d) { |
| int pv = i + 1; |
| if (x == pv) { |
| dd = i + 1; cc = 1; |
| } else { |
| auto [j, u] = solve(push_goto[i], push_val[i]); |
| if (cycle) return {-2, 0}; |
| if (j < 0 || j > d) { cycle = true; return {-2, 0}; } |
| auto [k, v] = solve(j, x); |
| if (cycle) return {-2, 0}; |
| dd = k; cc = (u + v + 1) % P; |
| } |
| } else { |
| if (x == 0) { |
| dd = -1; cc = 1; |
| } else { |
| auto [j, u] = solve(halt_goto, halt_push); |
| if (cycle) return {-2, 0}; |
| if (j < 0 || j > d) { cycle = true; return {-2, 0}; } |
| auto [k, v] = solve(j, x); |
| if (cycle) return {-2, 0}; |
| dd = k; cc = (u + v + 1) % P; |
| } |
| } |
|
|
| st[id] = 2; dest[id] = dd; cost[id] = cc; |
| return {dd, cc}; |
| }; |
|
|
| auto [_, T] = solve(0, 0); |
| total_attempts++; |
| if (cycle) continue; |
|
|
| |
| for (int iter = 0; iter < 30000; iter++) { |
| for (int ti = 0; ti < 2; ti++) { |
| if (!found[ti] && T == targets[ti]) { |
| found[ti] = true; |
| cerr << "FOUND n=" << n << " target" << (ti+1) << " T=" << T << endl; |
| cout << "TARGET" << (ti+1) << " n=" << n << endl; |
| cout << n << endl; |
| for (int i = 0; i < d; i++) { |
| cout << "POP " << (i+1) << " GOTO " << (i+2) |
| << " PUSH " << push_val[i] << " GOTO " << (push_goto[i]+1) << endl; |
| } |
| cout << "HALT PUSH " << halt_push << " GOTO " << (halt_goto+1) << endl; |
| } |
| } |
| if (found[0] && found[1]) break; |
|
|
| |
| int save_pv, save_pg, save_idx, save_hp, save_hg; |
| int mut = rng() % 3; |
| if (mut == 0 && d > 0) { |
| save_idx = rng() % d; |
| save_pv = push_val[save_idx]; |
| push_val[save_idx] = 1 + rng() % d; |
| } else if (mut == 1 && d > 0) { |
| save_idx = rng() % d; |
| save_pg = push_goto[save_idx]; |
| push_goto[save_idx] = rng() % (save_idx + 1); |
| } else { |
| save_hp = halt_push; save_hg = halt_goto; |
| halt_push = 1 + rng() % d; |
| halt_goto = rng() % d; |
| mut = 2; |
| } |
|
|
| |
| fill(st.begin(), st.end(), (int8_t)0); |
| cycle = false; |
| auto [_d, nT] = solve(0, 0); |
| total_attempts++; |
|
|
| bool accept = false; |
| if (!cycle) { |
| long long bestOld = P, bestNew = P; |
| for (int ti = 0; ti < 2; ti++) { |
| if (!found[ti]) { |
| bestOld = min(bestOld, min((T - targets[ti] + P) % P, (targets[ti] - T + P) % P)); |
| bestNew = min(bestNew, min((nT - targets[ti] + P) % P, (targets[ti] - nT + P) % P)); |
| } |
| } |
| accept = (bestNew <= bestOld); |
| } |
|
|
| if (accept) { |
| T = nT; |
| } else { |
| if (mut == 0) push_val[save_idx] = save_pv; |
| else if (mut == 1) push_goto[save_idx] = save_pg; |
| else { halt_push = save_hp; halt_goto = save_hg; } |
| } |
| } |
| } |
|
|
| auto ms = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - startTime).count(); |
| cerr << " attempts=" << total_attempts << " time=" << ms << "ms found=" << found[0] << "," << found[1] << endl; |
| if (found[0] && found[1]) break; |
| } |
|
|
| return 0; |
| } |
|
|