题目描述:
给你一个长度为50的数字串,问你有多少个子序列构成的数字可以被3整除
答案对1e9+7取模
输入描述:
输入一个字符串,由数字构成,长度小于等于50
输出描述:
输出一个整数
输入:
132
9
3
1
题意:
题目描述
题解:
因为是子序列,所以可以不连续,因此需要保存每个区间上余数为0,1,2的数目 用dp[i][k] 表示从0到i区间上,余数为k的数目.
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 55;
const int mod = 1e9+7;
char s[maxn];
ll dp[maxn][5];
int main(){
while(scanf("%s",s)!=EOF){
int l = strlen(s);
for(int i = 0; i < l; i ++){
int t = s[i] - '0';
t %= 3;
dp[i][t] = 1;
}
for(int i = 1; i < l; i ++){
int t = s[i] - '0';
if(t % 3 == 0){
dp[i][0] = 2 * dp[i - 1][0] + 1;
dp[i][1] = 2 * dp[i - 1][1];
dp[i][2] = 2 * dp[i - 1][2];
}
else if(t % 3 == 1){
dp[i][0] = dp[i - 1][0] + dp[i - 1][2];
dp[i][1] = dp[i - 1][1] + dp[i - 1][0] + 1;
dp[i][2] = dp[i - 1][1] + dp[i - 1][2];
}
else{
dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
dp[i][1] = dp[i - 1][1] + dp[i - 1][2];
dp[i][2] = dp[i - 1][2] + dp[i - 1][0] + 1;
}
for(int j = 0; j < 3; j ++){
dp[i][j] %= mod;
}
}
printf("%lld\n",dp[l - 1][0]);
}
}