bzoj1009: [HNOI2008]GT考试
AC自动机+矩阵快速幂。跟poj2778差不多。以前看题解kmp什么一直看不懂。。。然后我就用AC自动机水过去了。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long const int nmax=25; char s[nmax]; int ch[nmax][10],fail[nmax],F[nmax],pt=0,n,m,mod; void insert(){ int t=0,len=strlen(s); rep(i,0,len-1) { if(!ch[t][s[i]-'0']) ch[t][s[i]-'0']=++pt; t=ch[t][s[i]-'0']; } F[t]=1; } void getfail(){ queue<int>q;fail[0]=0;q.push(0); while(!q.empty()){ int x=q.front();q.pop(); rep(i,0,9) { if(ch[x][i]) q.push(ch[x][i]),fail[ch[x][i]]=x==0?0:ch[fail[x]][i]; else ch[x][i]=x==0?0:ch[fail[x]][i]; } F[x]|=F[fail[x]]; } } struct node{ int a[nmax][nmax]; node(){ clr(a,0); } node operator*(const node&o)const { node tmp; rep(i,0,pt) rep(j,0,pt) rep(k,0,pt) { tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*o.a[k][j])%mod; } return tmp; } }a,b; void getmatrix(){ rep(i,0,pt) a.a[i][i]=1; rep(i,0,pt) rep(j,0,9) if(!F[ch[i][j]]) b.a[i][ch[i][j]]++; while(n){ if(n&1) a=a*b; b=b*b;n>>=1; } int ans=0; rep(i,0,pt) ans=(ans+a.a[0][i])%mod; printf("%d\n",ans); } int main(){ scanf("%d%d%d",&n,&m,&mod); scanf("%s",s);insert();getfail(); //rep(i,0,pt) printf("%d ",fail[i]);printf("\n"); //rep(i,0,pt) printf("%d ",F[i]);printf("\n"); getmatrix(); return 0; }
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2918 Solved: 1801
[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
111
Sample Output
81