| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| static const long long P = 998244353; |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| |
|
|
| struct Evaluator { |
| int n; |
| |
| vector<int> pop_val; |
| vector<int> pop_goto; |
| vector<int> push_val; |
| vector<int> push_goto; |
| |
| int halt_push; |
| int halt_goto; |
|
|
| |
| vector<array<int, 1025>> dp_dest; |
| vector<array<long long, 1025>> dp_cost; |
| vector<array<int8_t, 1025>> dp_state; |
|
|
| bool has_cycle; |
|
|
| void init() { |
| dp_dest.assign(n, array<int, 1025>{}); |
| dp_cost.assign(n, array<long long, 1025>{}); |
| dp_state.assign(n, array<int8_t, 1025>{}); |
| has_cycle = false; |
| } |
|
|
| pair<int, long long> solve(int i, int x) { |
| if (has_cycle) return {-2, 0}; |
| if (dp_state[i][x] == 2) return {dp_dest[i][x], dp_cost[i][x]}; |
| if (dp_state[i][x] == 1) { has_cycle = true; return {-2, 0}; } |
| dp_state[i][x] = 1; |
|
|
| int dest; |
| long long cost; |
|
|
| if (i < n - 1) { |
| if (x == pop_val[i]) { |
| dest = pop_goto[i]; |
| cost = 1; |
| } else { |
| auto [j, u] = solve(push_goto[i], push_val[i]); |
| if (has_cycle) return {-2, 0}; |
| auto [k, v] = solve(j, x); |
| if (has_cycle) return {-2, 0}; |
| dest = k; |
| cost = (u + v + 1) % P; |
| } |
| } else { |
| if (x == 0) { |
| dest = -1; |
| cost = 1; |
| } else { |
| auto [j, u] = solve(halt_goto, halt_push); |
| if (has_cycle) return {-2, 0}; |
| auto [k, v] = solve(j, x); |
| if (has_cycle) return {-2, 0}; |
| dest = k; |
| cost = (u + v + 1) % P; |
| } |
| } |
|
|
| dp_state[i][x] = 2; |
| dp_dest[i][x] = dest; |
| dp_cost[i][x] = cost; |
| return {dest, cost}; |
| } |
| }; |
|
|
| int main() { |
| long long targets[2] = {150994941LL, 150994939LL}; |
|
|
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
|
|
| for (int n = 10; n <= 28; n++) { |
| cerr << "n=" << n << endl; |
| int d = n - 1; |
|
|
| mt19937 rng(42 + n * 1000003); |
| bool found[2] = {false, false}; |
| int foundConfig[2][35][2]; |
|
|
| auto startTime = chrono::steady_clock::now(); |
| int timeLimit = (n <= 15) ? 15000 : (n <= 20) ? 8000 : 3000; |
|
|
| for (int restart = 0; !(found[0] && found[1]); restart++) { |
| auto now = chrono::steady_clock::now(); |
| auto ms = chrono::duration_cast<chrono::milliseconds>(now - startTime).count(); |
| if (ms > timeLimit) break; |
|
|
| |
| |
| |
| |
| |
|
|
| Evaluator ev; |
| ev.n = n; |
| ev.pop_val.resize(d); |
| ev.pop_goto.resize(d); |
| ev.push_val.resize(d); |
| ev.push_goto.resize(d); |
| for (int i = 0; i < d; i++) { |
| ev.pop_val[i] = i + 1; |
| ev.pop_goto[i] = i + 1; |
| int maxPV = min(i + 2, 10); |
| ev.push_val[i] = 1 + rng() % maxPV; |
| ev.push_goto[i] = rng() % n; |
| } |
| ev.halt_push = 1; |
| ev.halt_goto = d; |
|
|
| |
| |
| ev.halt_goto = rng() % d; |
|
|
| ev.init(); |
| auto [dest, cost] = ev.solve(0, 0); |
| if (ev.has_cycle) continue; |
|
|
| |
| for (int iter = 0; iter < 50000; iter++) { |
| for (int ti = 0; ti < 2; ti++) { |
| if (!found[ti] && cost == targets[ti]) { |
| found[ti] = true; |
| cerr << "FOUND n=" << n << " target" << (ti+1) << " cost=" << cost << endl; |
| |
| cout << "FOUND n=" << n << " target" << (ti+1) << ":" << endl; |
| cout << n << endl; |
| for (int i = 0; i < d; i++) { |
| cout << "POP " << ev.pop_val[i] << " GOTO " << (ev.pop_goto[i]+1) |
| << " PUSH " << ev.push_val[i] << " GOTO " << (ev.push_goto[i]+1) << endl; |
| } |
| cout << "HALT PUSH " << ev.halt_push << " GOTO " << (ev.halt_goto+1) << endl; |
| } |
| } |
| if (found[0] && found[1]) break; |
|
|
| |
| int choice = rng() % (2 * d + 2); |
| Evaluator ev2 = ev; |
| |
| if (choice < d) { |
| |
| int maxPV = min(choice + 2, 10); |
| ev2.push_val[choice] = 1 + rng() % maxPV; |
| } else if (choice < 2*d) { |
| |
| ev2.push_goto[choice - d] = rng() % n; |
| } else if (choice == 2*d) { |
| |
| ev2.halt_push = 1 + rng() % 10; |
| } else { |
| |
| ev2.halt_goto = rng() % d; |
| } |
|
|
| ev2.init(); |
| auto [dest2, cost2] = ev2.solve(0, 0); |
| if (ev2.has_cycle) continue; |
|
|
| |
| long long bestDist = P; |
| for (int ti = 0; ti < 2; ti++) { |
| if (!found[ti]) { |
| long long dd = min((cost - targets[ti] + P) % P, (targets[ti] - cost + P) % P); |
| bestDist = min(bestDist, dd); |
| } |
| } |
| long long newBestDist = P; |
| for (int ti = 0; ti < 2; ti++) { |
| if (!found[ti]) { |
| long long dd = min((cost2 - targets[ti] + P) % P, (targets[ti] - cost2 + P) % P); |
| newBestDist = min(newBestDist, dd); |
| } |
| } |
|
|
| if (newBestDist <= bestDist) { |
| ev.push_val = ev2.push_val; |
| ev.push_goto = ev2.push_goto; |
| ev.halt_push = ev2.halt_push; |
| ev.halt_goto = ev2.halt_goto; |
| cost = cost2; |
| } |
| } |
| } |
|
|
| cerr << " found=" << found[0] << "," << found[1] << endl; |
| if (found[0] && found[1]) break; |
| } |
|
|
| return 0; |
| } |
|
|