Educational Codeforces Round 94 Editorial F
复杂度的问题(题解在下面)
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;
}