ZROI278 序列II 【数位dp】【状态压缩】

题意:对于一个序列 a a ,有:
|a|=m
ai[0,9] a i ∈ [ 0 , 9 ]
我们可以将每个序列 a a 的前缀a1..i看做一个可能含前导零的十进制数。
对于每一个 r[0,6] r ∈ [ 0 , 6 ] ,都存在至少一个 i[1,m] i ∈ [ 1 , m ] 使得 a1..i a 1.. i 写成的十进制数 mod 7=r m o d   7 = r
给出 m p m   p ,求方案数 mod p m o d   p 的值。

题解:
还有不到100天就要 NOIP 了,鉴于 NOIP2017 的惨痛教训,游记我是一定会写的,希望到时候自己能有一个很大的飞跃吧。
模拟赛现场AC简直不能更赞 ~~
dp[i][j][l] d p [ i ] [ j ] [ l ] 表示考虑到第 i i 位,模 7 状态为 j 1..(i1) 1.. ( i − 1 ) 所组成的数模 7 为 l l 的方案数
比如:j=(0010100)2,那么当前状态(前缀和目前)已经模 7=3 and 5 7 = 3   a n d   5
转移:
dp[i][j][l]=>dp[i+1][j|((1<<(l10+k)) d p [ i ] [ j ] [ l ] => d p [ i + 1 ] [ j | ( ( 1 << ( l ∗ 10 + k ) )
其中 k=0...9 k = 0...9
解释:枚举当前位,那么 1..i 1.. i 所组成的数模 7 就是 (l10+k) ( l ∗ 10 + k )

一开始一直困扰我的是如何记录前缀,后来才想明白我可以多开一维啊233333

代码:

// by Balloons
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() puts("okkkkkkkk")

using namespace std;

typedef long long LL;

const int inf = 1 << 30;

const int maxn=1e3+5;
int m,mod;
int dp[maxn][(1<<7)+5][8];
//int qz[maxn][(1<<7)+5];

int main(){
    //freopen("C.in","r",stdin);
    scanf("%d%d",&m,&mod);
    dp[m+1][0][0]=1;
    for(int i=m;i>=1;i--){
        for(int j=0;j<=(1<<7)-1;j++){
            for(int k=0;k<=9;k++){
                for(int l=0;l<7;l++){
                    (dp[i][j|(1<<((l*10+k)%7))][(l*10+k)%7]+=dp[i+1][j][l])%=mod;
                }
            }
        }
    }
    int ans=0;
    for(int i=0;i<7;i++)(ans+=dp[1][(1<<7)-1][i])%=mod;
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值