您的位置:首页 > 其它

BZOJ 1009: [HNOI2008]GT考试 AC自动机+矩阵快速幂

2015-05-12 21:29 399 查看
经典题目了....虽然只有一个不能出现的字符串,但还是写了ac自动机

1009: [HNOI2008]GT考试

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 2051  Solved: 1257

[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位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6

Output

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

Sample Input

4 3 100

111

Sample Output

81

HINT

Source



[Submit][Status][Discuss]

/* ***********************************************
Author :CKboss
Created Time :2015年05月12日 星期二 08时16分03秒
File Name :BZOJ1009.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;
const int maxn=1200;

int idx(char c) { return c-'0'; }

int ch[maxn][11],fail[maxn],end[maxn];
int root,sz;
char str[maxn];

int newnode()
{
memset(ch[sz],-1,sizeof(ch[sz]));
end[sz++]=0;
return sz-1;
}

void ac_init() { sz=0; root=newnode(); }

void ac_insert(char str[])
{
int len=strlen(str);
int now=root;
for(int i=0;i<len;i++)
{
int id=idx(str[i]);
if(ch[now][id]==-1) ch[now][id]=newnode();
now=ch[now][id];
}
end[now]++;
}

void ac_build()
{
queue<int> q;
fail[root]=root;
for(int i=0;i<10;i++)
{
if(ch[root][i]==-1)
ch[root][i]=root;
else
{
fail[ch[root][i]]=root;
q.push(ch[root][i]);
}
}
while(!q.empty())
{
int now=q.front(); q.pop();
end[now]+=end[fail[now]];
for(int i=0;i<10;i++)
{
if(ch[now][i]==-1)
ch[now][i]=ch[fail[now]][i];
else
{
fail[ch[now][i]]=ch[fail[now]][i];
q.push(ch[now][i]);
}
}
}
}

int n,m,mod;

typedef vector<int> vi;

struct MATRIX
{
int _x,_y;
int matrix[30][30];

MATRIX(){};
MATRIX(int n)
{
_x=_y=n;
memset(matrix,0,sizeof(matrix));
}

void getOne(int n)
{
for(int i=0;i<n;i++)
matrix[i][i]=1;
}

MATRIX operator* (const MATRIX& b) const
{
int n=b._x;
MATRIX ret(n);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
int temp=0;
for(int k=0;k<n;k++)
{
temp=(temp+matrix[i][k]*b.matrix[k][j])%mod;
}
ret.matrix[i][j]=temp%mod;
}
}
return ret;
}
};

MATRIX QuickPow(MATRIX M,int n)
{
MATRIX ans;
ans.getOne(M._x);
while(n)
{
if(n&1) ans=ans*M;
M=M*M;
n/=2;
}
return ans;
}

int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);

scanf("%d%d%d",&n,&m,&mod);
scanf("%s",str);

ac_init();
ac_insert(str);
ac_build();

MATRIX mat(sz);

for(int i=0;i<sz;i++)
{
if(end[i]) continue;
for(int j=0;j<10;j++)
{
int p=ch[i][j];
if(end[p]||end[fail[p]]) continue;
mat.matrix[i][p]++;
}
}

MATRIX ret=QuickPow(mat,n);

int ans=0;

for(int i=0;i<sz;i++)
{
ans=(ans+ret.matrix[0][i])%mod;
}

printf("%d\n",ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: