被3整除的子序列(闫氏DP分析法)
题目链接:https://ac.nowcoder.com/acm/problem/21302
核心思路:类似于01背包问题
- 状态表示:
- dp[i][j]:仅仅由前i个字符组成,且和为j的方案总数
- 状态属性:
- 单纯求出每一个dp[i][j]即可
- 状态计算:
- 对于第k个位置的字符x,有两种方案:选与不选
- 不选第k个位置的字符:dp[i][j] = dp[i - 1][j]
- 选第k个位置的字符:dp[i][j] = dp[i][j] + dp[i - 1][j - x]
- 对于第k个位置的字符x,有两种方案:选与不选
最后的答案应该是所有j为3的倍数的dp[length][j]之和
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll dp[55][550];
int main() {
string s; cin >> s;
s = ' ' + s;
for(int i = 1; i < s.size(); i++)
for(int j = 0; j <= 450; j++) {
dp[i][j] = dp[i - 1][j];
int x = s[i] - '0';
if(j == x) dp[i][j]++;
if(j >= x) dp[i][j] = (dp[i][j] + dp[i - 1][j - x] + mod) % mod;
}
ll res = 0;
for(int i = 0; i <= 450; i++)
if(i % 3 == 0)
res = (res + dp[s.size() - 1][i] + mod) % mod;
cout << res % mod << endl;
return 0;
}

浙公网安备 33010602011771号