bzoj1009: [HNOI2008]GT考试 ac自动机+矩阵快速幂
https://www.lydsy.com/JudgeOnline/problem.php?id=1009
阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0
在构造好的next图上跑矩阵快速幂即可
/************************************************************** Problem: 1009 User: walfy Language: C++ Result: Accepted Time:120 ms Memory:1384 kb ****************************************************************/ //#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> //#define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=200+10,maxn=200000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; ll n,m,k; struct Node{ ll row,col; ll a[30][30]; }; Node mul(Node x,Node y,ll mod) { Node ans; ans.row=x.row,ans.col=y.col; memset(ans.a,0,sizeof ans.a); for(int i=0;i<x.row;i++) for(int j=0;j<x.col;j++) for(int k=0;k<y.col;k++) ans.a[i][k]=(ans.a[i][k]+x.a[i][j]*y.a[j][k]+mod)%mod; return ans; } Node quick_mul(Node x,ll n,ll mod) { Node ans; ans.row=x.row,ans.col=x.col; memset(ans.a,0,sizeof ans.a); for(int i=0;i<ans.col;i++)ans.a[i][i]=1; while(n){ if(n&1)ans=mul(ans,x,mod); x=mul(x,x,mod); n/=2; } return ans; } char s[N]; struct ACM{ int root,tot; int Next[N*10][10],fail[N],End[N*10]; int newnode() { memset(Next[tot],-1,sizeof Next[tot]); End[tot]=0; return tot++; } ACM() { tot=0; root=newnode(); } void ins() { int now=root,len=strlen(s); for(int i=0;i<len;i++) { if(Next[now][s[i]-'0']==-1) Next[now][s[i]-'0']=newnode(); now=Next[now][s[i]-'0']; } End[now]=1; } void build() { queue<int>q; fail[root]=root; for(int i=0;i<10;i++) { if(Next[root][i]==-1)Next[root][i]=root; else { fail[Next[root][i]]=root; q.push(Next[root][i]); } } while(!q.empty()) { int now=q.front(); q.pop(); if(End[fail[now]])End[now]=1; for(int i=0;i<10;i++) { if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i]; else { fail[Next[now][i]]=Next[fail[now]][i]; q.push(Next[now][i]); } } } } void solve() { Node A; A.row=A.col=tot; for(int i=0;i<tot;i++) for(int j=0;j<10;j++) if(!End[Next[i][j]]) A.a[i][Next[i][j]]++; A=quick_mul(A,n,k); ll ans=0; for(int i=0;i<tot;i++) ans=(ans+A.a[0][i])%k; printf("%lld\n",ans); } }ac; int main() { scanf("%lld%lld%lld%s",&n,&m,&k,s); ac.ins(); ac.build(); ac.solve(); return 0; } /*********************** ***********************/