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 MB
Submit: 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

Sample Output

81

HINT

 

Source

 
[Submit][Status][Discuss]
posted @ 2016-07-30 20:09  BBChq  阅读(254)  评论(0编辑  收藏  举报