您的位置:首页 > 其它

BZOJ 1009 [HNOI2008]GT考试

2016-07-17 10:11 344 查看
Description

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

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

【题目分析】

题目的背景比较扯淡。谁能决定自己的准考证号,f[i][j]表示匹配到了i位,指针此时指向j的状态数。

然后每一位暴力的用KMP求出转移的矩阵,(详见代码)。然后来一波矩阵乘法。就可以了。

【代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,m,mod,j=0;
char s[25];
int next[25],b[25][25],a[25][25];
int now[25][25],sum=0;
void mul(int a[25][25],int b[25][25])
{
int c[25][25];
memset(c,0,sizeof c);
for (int i=0;i<m;++i)
for (int j=0;j<m;++j)
for (int k=0;k<m;++k)
(c[i][j]+=a[i][k]*b[k][j])%=mod;
for (int i=0;i<m;++i)
for (int j=0;j<m;++j)
a[i][j]=c[i][j];
}
int main()
{
scanf("%d%d%d",&n,&m,&mod);
scanf("%s",s+1);
for (int i=2;i<=m;++i)
{
while (j>0&&s[j+1]!=s[i]) j=next[j];
if (s[j+1]==s[i]) ++j;
next[i]=j;
}
for (int i=0;i<m;++i)
for (int j=0;j<=9;++j)
{
int k=i;
while (k>0&&s[k+1]-'0'!=j) k=next[k];
if (s[k+1]-'0'==j) ++k;
if (k!=m) (b[k][i]+=1)%=mod;
}int i=0;i<m;++i) a[i][i]=1;
while (n)
{
if (n&1) mul(a,b);
mul(b,b);
n>>=1;
}
for (int i=0;i<m;++i) (sum+=a[i][0])%=mod;
printf("%d\n",sum);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj