原题:牛客网
动态规划dynamic programming 的入门级题目
题目描述 :
给你一个长度为50的数字串,问你有多少个子序列构成的数字可以被3整除
答案对1e9+7取模
输入描述:
输入一个字符串,由数字构成,长度小于等于50
输出描述:
输出一个整数
示例
输入:

132
输出:
3
正确代码

#include <bits/stdc++.h>
using namespace std;
const int Mod=1e9+7;
int dp[3];
char a1[55];
int  main()
{

    cin.getline(a1,55);
    memset(dp,0, sizeof(dp));
    int n=strlen(a1);
    for(int i=0;i<n;i++)
    {
        int s0=0,s1=0,s2=0;
        int x=a1[i]-'0';
        if(x%3==0){
            s0+=dp[0]+1;
            s1+=dp[1];
            s2+=dp[2];
        }
        if(x%3==1){
            s0+=dp[2];
            s1+=dp[0]+1;
            s2+=dp[1];
        }
        if(x%3==2){
            s0+=dp[1];
            s1+=dp[2];
            s2+=dp[0]+1;
        }
        dp[0]+=s0;
        dp[1]+=s1;
        dp[2]+=s2;
        for(int j=0;j<3;j++)
            dp[j]=dp[j]%Mod;
    }
    cout<<dp[0]<<endl;


}

题目认知:
子序列与子串的区别在于连续与否,子串连续,子序列不连续,因此根据题意我们要对所有子序列进行判断是否满足题意和满足题意的子序列的个数有多少个,最后对结果取余数,取余数时,无论是最后一起取余,还是分步取余结果都是一样的,因此,分步取余更易于存储。
对于如何对子序列进行判断
就上文中的正确代码里,我使用了一个for循环对整个数组进行一次遍历,一次遍历即可求出所要结果。
就dp思想而言,我们应该将大问题化为小问题,逐个对小问题进行求解,因此应该考虑如何分离子序列,然后再对子序列进行判断。