被3整除的子序列题解报告

题目链接
题目大意
给你一个长度为 50 的数字串,问你有多少个子序列构成的数字可以被 3 整除
答案对 1 e 9 + 7 1e^9+7 1e9+7取模
输入描述
输入一个字符串,由数字构成,长度小于等于50
输出描述
输出一个整数
输入样例

132

输出样例

3

动态规划线性dp
1.确定状态 f [ i ] [ j ] f[i][j] f[i][j]:以 s [ i ] s[i] s[i] 结尾的数余数是 j j j,属性表示方案数。
2.状态转移 f [ i + 1 ] [ j ] = f [ i + 1 ] [ j ] + f [ i ] [ j ] f[i+1][j] = f[i+1][j] + f[i][j] f[i+1][j]=f[i+1][j]+f[i][j]

举个粟子,以样例为例。首先132的子序列有 1、3、13、2、12、32、132,有个结论就是一个数能被某个数整除,那么所有位置上的数字之和能被这个数整除,以 2 结尾的数据有 2、12、32、132 。12 可以看作 f [ " 12 " ] [ m o d ] = f [ " 12 " ] [ ( m o d + " 2 " ) % m o d ] + f [ " 1 " ] [ m o d ] f["12"][mod] = f["12"][(mod+"2")\%mod] + f["1"][mod] f["12"][mod]=f["12"][(mod+"2")%mod]+f["1"][mod]依次类推。
3.编码实现方式

1      dp[1][1] = 1;
03     dp[2][0] = 1;
002    dp[3][2] = 1;

112  
13132 ⇒ dp[3][(j+2)%3] = (dp[2][j] + dp[3][(j+2)%3])
2
332

for(int i = 1; i <= len; i++)
    for(int j = 0; j < 3; j++)
        for(int k = i+1; k <= len; k++)
            f[k][(s[k]+j-'0')%3] =(f[k][(s[k]+j-'0')%3]+ f[i][j])%mod;
#include <cstdio>
#include <cstring>
using namespace std;
const int mod = 1e9 + 7;
char s[55];
int f[55][3];
int main()
{
    
    
    scanf("%s",s+1);
    int len = strlen(s+1);
    for(int i = 1; i <= len; i++) f[i][(s[i]-'0')%3] = 1;
    
    for(int i = 1; i <= len; i++)
        for(int j = 0; j < 3; j++)
            for(int k = i+1; k <= len; k++)
                f[k][(s[k]+j-'0')%3] =(f[k][(s[k]+j-'0')%3]+ f[i][j])%mod;
       
    int ans = 0;
    for(int i = 1; i <= len; i++) ans = (ans + f[i][0])%mod;
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Edviv/article/details/110931489
今日推荐