| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| static const long long P = 998244353; |
|
|
| |
| |
| struct Program { |
| int n; |
| |
| |
| |
| vector<int> type; |
| vector<array<int, 4>> params; |
|
|
| |
| vector<vector<optional<pair<int, long long>>>> dp; |
| vector<vector<bool>> vis; |
| bool has_cycle; |
|
|
| void init() { |
| dp.assign(n, vector<optional<pair<int, long long>>>(1025, nullopt)); |
| vis.assign(n, vector<bool>(1025, false)); |
| has_cycle = false; |
| } |
|
|
| pair<int, long long> solve(int i, int x) { |
| if (has_cycle) return {-2, 0}; |
| if (dp[i][x]) return dp[i][x].value(); |
| if (vis[i][x]) { has_cycle = true; return {-2, 0}; } |
| vis[i][x] = true; |
|
|
| if (type[i] == 0) { |
| int pop_val = params[i][0], pop_goto = params[i][1]; |
| int push_val = params[i][2], push_goto = params[i][3]; |
| if (x == pop_val) { |
| dp[i][x] = {pop_goto, 1}; |
| } else { |
| auto [j, u] = solve(push_goto, push_val); |
| if (has_cycle) return {-2, 0}; |
| auto [k, v] = solve(j, x); |
| if (has_cycle) return {-2, 0}; |
| dp[i][x] = {k, (u + v + 1) % P}; |
| } |
| } else { |
| int push_val = params[i][0], push_goto = params[i][1]; |
| if (x == 0) { |
| dp[i][x] = {-1, 1}; |
| } else { |
| auto [j, u] = solve(push_goto, push_val); |
| if (has_cycle) return {-2, 0}; |
| auto [k, v] = solve(j, x); |
| if (has_cycle) return {-2, 0}; |
| dp[i][x] = {k, (u + v + 1) % P}; |
| } |
| } |
| return dp[i][x].value(); |
| } |
| }; |
|
|
| int main() { |
| long long targets[2] = {150994941LL, 150994939LL}; |
|
|
| |
| |
| int V = 5; |
|
|
| for (int n = 2; n <= 6; n++) { |
| cerr << "n=" << n << endl; |
| |
| |
|
|
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
|
|
| int maxV; |
| if (n <= 3) maxV = 20; |
| else if (n == 4) maxV = 4; |
| else if (n == 5) maxV = 3; |
| else maxV = 2; |
|
|
| long long count = 0; |
| bool found[2] = {false, false}; |
|
|
| auto startTime = chrono::steady_clock::now(); |
|
|
| |
| mt19937 rng(42 + n * 17); |
|
|
| |
| bool exhaustive = false; |
| long long totalConfigs = 1; |
| for (int i = 0; i < n - 1; i++) totalConfigs *= (long long)maxV * n * maxV * n; |
| totalConfigs *= (long long)maxV * n; |
| if (totalConfigs <= 50000000) exhaustive = true; |
|
|
| cerr << " maxV=" << maxV << " totalConfigs=" << totalConfigs << " exhaustive=" << exhaustive << endl; |
|
|
| if (exhaustive) { |
| |
| |
| |
| |
| int ndim = 4 * (n - 1) + 2; |
| vector<int> radix(ndim); |
| for (int i = 0; i < n - 1; i++) { |
| radix[4*i] = maxV; |
| radix[4*i+1] = n; |
| radix[4*i+2] = maxV; |
| radix[4*i+3] = n; |
| } |
| radix[ndim-2] = maxV; |
| radix[ndim-1] = n; |
|
|
| vector<int> idx(ndim, 0); |
|
|
| while (true) { |
| Program prog; |
| prog.n = n; |
| prog.type.resize(n); |
| prog.params.resize(n); |
| for (int i = 0; i < n - 1; i++) { |
| prog.type[i] = 0; |
| prog.params[i][0] = idx[4*i] + 1; |
| prog.params[i][1] = idx[4*i+1]; |
| prog.params[i][2] = idx[4*i+2] + 1; |
| prog.params[i][3] = idx[4*i+3]; |
| } |
| prog.type[n-1] = 1; |
| prog.params[n-1][0] = idx[ndim-2] + 1; |
| prog.params[n-1][1] = idx[ndim-1]; |
|
|
| prog.init(); |
| auto [dest, cost] = prog.solve(0, 0); |
| if (!prog.has_cycle) { |
| for (int ti = 0; ti < 2; ti++) { |
| if (!found[ti] && cost == targets[ti]) { |
| found[ti] = true; |
| cout << "FOUND n=" << n << " target" << (ti+1) << " cost=" << cost << endl; |
| cout << n << endl; |
| for (int i = 0; i < n - 1; i++) { |
| cout << "POP " << prog.params[i][0] << " GOTO " << (prog.params[i][1]+1) |
| << " PUSH " << prog.params[i][2] << " GOTO " << (prog.params[i][3]+1) << endl; |
| } |
| cout << "HALT PUSH " << prog.params[n-1][0] << " GOTO " << (prog.params[n-1][1]+1) << endl; |
| } |
| } |
| } |
|
|
| count++; |
| if (count % 1000000 == 0) { |
| auto now = chrono::steady_clock::now(); |
| auto ms = chrono::duration_cast<chrono::milliseconds>(now - startTime).count(); |
| cerr << " count=" << count << " (" << ms << "ms)" << endl; |
| } |
|
|
| |
| int pos = ndim - 1; |
| while (pos >= 0) { |
| idx[pos]++; |
| if (idx[pos] < radix[pos]) break; |
| idx[pos] = 0; |
| pos--; |
| } |
| if (pos < 0) break; |
| if (found[0] && found[1]) break; |
| } |
| } else { |
| |
| long long maxAttempts = 100000000LL; |
| for (long long att = 0; att < maxAttempts; att++) { |
| Program prog; |
| prog.n = n; |
| prog.type.resize(n); |
| prog.params.resize(n); |
| for (int i = 0; i < n - 1; i++) { |
| prog.type[i] = 0; |
| prog.params[i][0] = 1 + rng() % maxV; |
| prog.params[i][1] = rng() % n; |
| prog.params[i][2] = 1 + rng() % maxV; |
| prog.params[i][3] = rng() % n; |
| } |
| prog.type[n-1] = 1; |
| prog.params[n-1][0] = 1 + rng() % maxV; |
| prog.params[n-1][1] = rng() % n; |
|
|
| prog.init(); |
| auto [dest, cost] = prog.solve(0, 0); |
| if (!prog.has_cycle) { |
| for (int ti = 0; ti < 2; ti++) { |
| if (!found[ti] && cost == targets[ti]) { |
| found[ti] = true; |
| cout << "FOUND n=" << n << " target" << (ti+1) << " cost=" << cost << endl; |
| cout << n << endl; |
| for (int i = 0; i < n - 1; i++) { |
| cout << "POP " << prog.params[i][0] << " GOTO " << (prog.params[i][1]+1) |
| << " PUSH " << prog.params[i][2] << " GOTO " << (prog.params[i][3]+1) << endl; |
| } |
| cout << "HALT PUSH " << prog.params[n-1][0] << " GOTO " << (prog.params[n-1][1]+1) << endl; |
| } |
| } |
| } |
|
|
| count++; |
| if (count % 10000000 == 0) { |
| auto now = chrono::steady_clock::now(); |
| auto ms = chrono::duration_cast<chrono::milliseconds>(now - startTime).count(); |
| cerr << " count=" << count << " (" << ms << "ms)" << endl; |
| if (ms > 30000) break; |
| } |
| if (found[0] && found[1]) break; |
| } |
| } |
|
|
| cerr << " total=" << count << " found=" << found[0] << "," << found[1] << endl; |
| if (found[0] && found[1]) { |
| cerr << "Both found at n=" << n << "!" << endl; |
| break; |
| } |
| } |
|
|
| return 0; |
| } |
|
|