用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'; }
|