您的位置:首页 > 其它

bzoj1009【HNOI2008】GT考试

2016-05-11 00:27 423 查看

1009: [HNOI2008]GT考试

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 2761  Solved: 1702

[Submit][Status][Discuss]

Description

  阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。

他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为

0

Input

  第一行输入N,M,K.接下来一行输入M位的数。 N<=10^9,M<=20,K<=1000

Output

  阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.

Sample Input

4 3 100

111

Sample Output

81

KMP+矩阵乘法快速幂优化DP

f[i][j]表示Xi匹配到Aj的方案数,最终答案等于f
[0]+f
[1]+…+f
[m-1]。

结合KMP算法可以推导出DP方程,然后会发现f[i][]只和f[i-1][]有关。所以我们可以将状态转移变为一个矩阵,用矩阵乘法快速幂优化时间复杂度。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
using namespace std;
int n,m,p,ans;
int nxt[30];
char s[30];
struct matrix
{
int f[30][30];
matrix(){memset(f,0,sizeof(f));}
friend matrix operator *(matrix a,matrix b)
{
matrix c;
F(i,0,m-1) F(j,0,m-1) F(k,0,m-1) (c.f[i][j]+=a.f[i][k]*b.f[k][j])%=p;
return c;
}
}a,b;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void getnxt()
{
int i=1,j=0;
nxt[1]=0;
while (i<=m)
{
if (j==0||s[i]==s[j]) nxt[++i]=++j;
else j=nxt[j];
}
}
int main()
{
n=read();m=read();p=read();
scanf("%s",s+1);
getnxt();
F(i,0,m-1) a.f[i][i]=1;
F(i,1,m) F(j,0,9)
{
int t=i;
while (t&&s[t]-'0'!=j) t=nxt[t];
b.f[i-1][t]++;
}
F(i,0,m-1) F(j,0,m-1) b.f[i][j]%=p;
for(;n;n>>=1,b=b*b) if (n&1) a=a*b;
F(i,0,m-1) ans=(ans+a.f[0][i])%p;
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: