BZOJ 1009: [HNOI2008]GT考试 AC自动机+矩阵快速幂
2015-05-12 21:29
399 查看
经典题目了....虽然只有一个不能出现的字符串,但还是写了ac自动机
Submit: 2051 Solved: 1257
[Submit][Status][Discuss]
111
[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;
}
1009: [HNOI2008]GT考试
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 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可以为0Input
第一行输入N,M,K.接下来一行输入M位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6Output
阿申想知道不出现不吉利数字的号码有多少种,输出模K取余的结果.Sample Input
4 3 100111
Sample Output
81HINT
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;
}
相关文章推荐
- BZOJ 1009--[HNOI2008]GT考试【KMP算法】【矩阵优化线性递推】
- 【bzoj1009】[HNOI2008]GT考试
- AC日记——[HNOI2008]GT考试 bzoj 1009
- 【DP+矩阵优化】[HNOI2008][HYSBZ/BZOJ1009]GT考试
- BZOJ_1009_[HNOI2008]GT考试_KMP+矩阵乘法
- [Bzoj1009][HNOI2008]GT考试(KMP)(矩乘优化DP)
- [BZOJ 1009] [HNOI2008] GT考试 【AC自动机 + 矩阵乘法优化DP】
- bzoj 1009: [HNOI2008]GT考试(dp+kmp+矩阵快速幂)
- bzoj 1009: [HNOI2008]GT考试
- BZOJ1009 [HNOI2008]GT考试 矩阵
- 【BZOJ】1009: [HNOI2008]GT考试(dp+矩阵乘法+kmp+神题)
- [BZOJ1009][HNOI2008]GT考试(AC自动机+矩阵加速dp)
- _bzoj1009 [HNOI2008]GT考试【矩阵加速dp】
- bzoj1009 [HNOI2008]GT考试
- [KMP+矩阵快速幂加速]BZOJ 1009——[HNOI2008]GT考试
- [矩阵乘法+KMP] BZOJ1009: [HNOI2008]GT考试
- BZOJ1009: [HNOI2008]GT考试
- 【BZOJ1009】[HNOI2008]GT考试 next数组+矩阵乘法
- 【bzoj1009】[HNOI2008]GT考试
- BZOJ1009 - [HNOI2008]GT考试