被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
",dp[n][0]%P);
    return 0;
}

原文地址:https://www.cnblogs.com/A-sc/p/12275828.html