题意:对于一个序列
a
a
,有:
ai∈[0,9]
a
i
∈
[
0
,
9
]
我们可以将每个序列
a
a
的前缀看做一个可能含前导零的十进制数。
对于每一个
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 状态为 ,
1..(i−1)
1..
(
i
−
1
)
所组成的数模 7 为
l
l
的方案数
比如:,那么当前状态(前缀和目前)已经模
7=3 and 5
7
=
3
a
n
d
5
转移:
dp[i][j][l]=>dp[i+1][j|((1<<(l∗10+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 就是
(l∗10+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;
}