File size: 3,430 Bytes
1fd0050
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Find the maximum step count achievable with n instructions and alphabet A
// Use random sampling + hill climbing to maximize T
#include <bits/stdc++.h>
using namespace std;

constexpr long long P = 998244353;

int n_instr, maxChar;
int type_arr[30];
int pop_c[30], g1[30], push_c[30], g2[30];

optional<pair<int, long long>> dp[30][1030];
bool vis[30][1030];
bool inf_flag;

pair<int, long long> solve(int i, int x) {
    if (dp[i][x]) return dp[i][x].value();
    if (vis[i][x]) { inf_flag = true; return {-1, 0}; }
    vis[i][x] = true;
    if (type_arr[i] == 0) {
        if (x == pop_c[i]) { dp[i][x] = {g1[i], 1LL}; }
        else {
            auto [j, u] = solve(g2[i], push_c[i]);
            if (inf_flag) return {-1, 0};
            auto [k, v] = solve(j, x);
            if (inf_flag) return {-1, 0};
            dp[i][x] = {k, (u + v + 1) % P};
        }
    } else {
        if (x == 0) { dp[i][x] = {-1, 1LL}; }
        else {
            auto [j, u] = solve(g2[i], push_c[i]);
            if (inf_flag) return {-1, 0};
            auto [k, v] = solve(j, x);
            if (inf_flag) return {-1, 0};
            dp[i][x] = {k, (u + v + 1) % P};
        }
    }
    return dp[i][x].value();
}

long long eval_prog() {
    for (int i = 0; i < n_instr; i++)
        for (int j = 0; j <= maxChar; j++) {
            dp[i][j].reset();
            vis[i][j] = false;
        }
    inf_flag = false;
    auto [fi, steps] = solve(0, 0);
    if (inf_flag) return -1;
    return steps;
}

int main() {
    mt19937 rng(42);

    // For each (n, A), find max T achievable
    for (int n = 2; n <= 10; n++) {
        for (int A : {n, n+2, 2*n, 3*n, min(30, 5*n)}) {
            n_instr = n;
            maxChar = A;
            long long global_max = 0;

            for (int restart = 0; restart < 10000; restart++) {
                // Random program
                for (int i = 0; i < n; i++) {
                    type_arr[i] = (i == n-1) ? 1 : 0;
                    if (type_arr[i] == 0) {
                        pop_c[i] = 1 + rng() % A;
                        g1[i] = rng() % n;
                        push_c[i] = 1 + rng() % A;
                        g2[i] = rng() % n;
                    } else {
                        push_c[i] = 1 + rng() % A;
                        g2[i] = rng() % n;
                    }
                }

                long long T = eval_prog();
                if (T < 0) continue;

                // Hill climb to maximize T
                for (int iter = 0; iter < 5000; iter++) {
                    int i = rng() % n;
                    int sv_pop = pop_c[i], sv_g1 = g1[i], sv_push = push_c[i], sv_g2 = g2[i];
                    int what = rng() % 4;
                    if (what == 0 && type_arr[i] == 0) pop_c[i] = 1 + rng() % A;
                    else if (what == 1) push_c[i] = 1 + rng() % A;
                    else if (what == 2) g2[i] = rng() % n;
                    else if (type_arr[i] == 0) g1[i] = rng() % n;

                    long long nT = eval_prog();
                    if (nT > T) T = nT;
                    else { pop_c[i] = sv_pop; g1[i] = sv_g1; push_c[i] = sv_push; g2[i] = sv_g2; }
                }

                if (T > global_max) global_max = T;
            }

            printf("n=%d A=%d: maxT=%lld (chain max=%lld, P=%d)\n",
                n, A, global_max, min((1LL<<(n))-1, (long long)P), P);
        }
    }

    return 0;
}