暑假牛客竞赛第四场K题 dp

用DP转移,复杂度为O(300N)

用$dp[i][j]$ 代表 末尾是第 i 个数字(i从1开始)对300取余为j的个数。

假设我们已经求得$dp[i][j]$

那么用一个循环就能得到$dp[i + 1][j]$

1
2
3
4
for(int j = 0; j < 300; ++j)
{
dp[i+1][(j * 10 + s[i] - '0') % 300] += dp[i][j]
}
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
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

typedef long long ll;

ll dp[100005][301];

int main()
{
string s;
cin >> s;
int sz = s.size();
for(int i = 1; i < s.size(); ++i)
{
dp[i][s[i - 1]-'0']++;
for(int j = 0; j < 300; ++j)
{
dp[i + 1][(j * 10 + s[i]-'0') % 300] += dp[i][j];
}
}
dp[sz][s[sz - 1] - '0']++;
ll ans = 0;
for(int i = 1; i <= sz; ++i)
{
ans += dp[i][0];
}
cout << ans << '\n';
}