被3整除的子序列/子串 (dp)
被3整除的子序列
题目: 给你一个长度为50的数字串,问你有多少个子序列构成的数字可以被3整除
答案对1e9+7取模
题解:
- 将所有字符转成数字在对3取模,那么序列中只有0,1,2三个数字
- 如果是子序列,那么 \(dp[i][0]\) 表示\(1到i\) 中子序列和模3等于0的个数,\(dp[i][1]\) 和 \(dp[i][2]\) 理。
- 如果是字串, \(dp[i][0]\) 表示以 i处结尾的字串和模3等于0的个数。最后答案为 \(\sum_{i=1}^{n}dp[i][0]\)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MA=1e5+5;
const int P=1e9+7;
char str[100];
int a[MA],dp[MA][3];
int main()
{
scanf("%s",str+1);
int n=strlen(str+1);
for(int i=1;i<=n;++i) {
a[i]=(str[i]-'0')%3;
if(a[i]==0) {
dp[i][0]=(dp[i-1][0]+dp[i-1][0]%P+1)%P;
dp[i][1]=(dp[i-1][1]+dp[i-1][1])%P;
dp[i][2]=(dp[i-1][2]+dp[i-1][2])%P;
}
else if(a[i]==1) {
dp[i][0]=(dp[i-1][0]+dp[i-1][2])%P;
dp[i][1]=(dp[i-1][1]+dp[i-1][0]+1)%P;
dp[i][2]=(dp[i-1][2]+dp[i-1][1])%P;
}
else if(a[i]==2){
dp[i][0]=(dp[i-1][0]+dp[i-1][1])%P;
dp[i][1]=(dp[i-1][1]+dp[i-1][2])%P;
dp[i][2]=(dp[i-1][2]+dp[i-1][0]+1)%P;
}
}
printf("%d\n",dp[n][0]%P);
return 0;
}