被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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幸愉聊信奥

谢谢亲的支持,我会继续努力啦~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值