Educational Codeforces Round 94 Editorial F
阿新 • • 發佈:2020-09-07
複雜度的問題(題解在下面)
x <= 20, 我們可以, 暴力把所有的 x-prime 跑出來, 這是跑出 x = 1 ~ 20 並插入ac自動機 每次 大約 所需要計算次數
#include <bits/stdc++.h> #define all(n) (n).begin(), (n).end() #define se second #define fi first #define pb push_back #define mp make_pair #define sqr(n) (n)*(n) #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) using namespace std; typedef long long ll; typedef pair<int, int> PII; typedef pair<ll, ll> PLL; typedef vector<int> VI; const int N = 3e5 + 5; int n, m, _, k; int a[21]; long long ans = 0; bool check(int k) { rep (i, 1, n) { int cur = 0; rep (j, i, n) { ans += 3; cur += a[j]; if (cur != n && n % cur == 0) return 0; } } return 1; } void dfs(int x, int y) { if (!y) { if (check(x - 1)) ans += (x << 1); return; } rep (i, 1, min(y, 9)) ans += 4, a[x] = i, dfs(x + 1, y - i); } int main() { IOS; rep (i, 1, 20) ans = 0, dfs(1, i), cout << ans << '\n'; return 0; }
1~20 所需的計算數量
8
22
52
116
252
540
1148
2428
5116
10740
22492
47000
98020
204060
424124
880188
1824124
3775484
7804924
16116742
不會超過2e8的數量級, 也就是1s可以跑出來, 題目給的是2s, 剩下的時間可以用來解決本題
題解
暴力跑出所有符合 x-prime 的字串加入ac自動機
f[i][j] 表示字串 第i個字元處在 自動機第 j 個節點,, 的最小花費
只要轉移的時候不走到自動機的字串結尾節點, 就不會有 x-prime, 哪怕你在節點 0
#include <bits/stdc++.h> #define all(n) (n).begin(), (n).end() #define se second #define fi first #define pb push_back #define mp make_pair #define sqr(n) (n)*(n) #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define per(i,a,b) for(int i=(a);i>=(b);--i) #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr) using namespace std; typedef long long ll; typedef pair<int, int> PII; typedef pair<ll, ll> PLL; typedef vector<int> VI; const int N = 5e3 + 5; int n, m, _, k; int a[21], x, len = 1; int f[2][N]; char s[1005]; namespace AC { const int C = 1; const int M = 9; struct ACstruct { int trie[N][M], fail[N]; bool ended[N]; int q[N], tot; void insert(int k) { int p = 0; rep(i, 1, k) { int ch = a[i] - C; if (!trie[p][ch]) trie[p][ch] = ++tot; p = trie[p][ch]; } ended[p] = 1; } void build() { int head = 0, tail = -1; rep(i, 0, M - 1) if (trie[0][i]) q[++tail] = trie[0][i]; while (head <= tail) { int p = q[head++]; rep(i, 0, M - 1) if (trie[p][i]) fail[trie[p][i]] = trie[fail[p]][i], q[++tail] = trie[p][i]; else trie[p][i] = trie[fail[p]][i]; } } }ac; } bool check(int k) { rep(i, 1, k) { int cur = 0; rep(j, i, k) { cur += a[j]; if (cur != x && x % cur == 0) return 0; } } return 1; } void dfs(int x, int y) { if (!y) { if (check(x - 1)) AC::ac.insert(x - 1); return; } rep(i, 1, min(y, 9)) a[x] = i, dfs(x + 1, y - i); } int main() { IOS; cin >> s + 1 >> x; memset(f[0], 0x3f, sizeof f[0]); dfs(1, x); AC::ac.build(); f[0][0] = 0; for (int& i = len; s[i]; ++i) { int a = i & 1, b = a ^ 1, ch = s[i] - '1'; memset(f[a], 0x3f, sizeof f[a]); rep(j, 0, AC::ac.tot) if (f[b][j] != 0x3f3f3f3f) { f[a][j] = min(f[a][j], f[b][j] + 1); int v = AC::ac.trie[j][ch]; if (!AC::ac.ended[v]) f[a][v] = min(f[a][v], f[b][j]); } }--len; int ans = len; rep(i, 0, AC::ac.tot) ans = min(ans, f[len & 1][i]); cout << ans; return 0; }