题目描述
阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字。他的不吉利数学A1A2...Am(0<=Ai<=9)有M位,不出现是指X1X2...Xn中没有恰好一段等于A1A2...Am. A1和X1可以为0
输入格式
第一行输入N,M,K.接下来一行输入M位的数。 100%数据N<=10^9,M<=20,K<=1000 40%数据N<=1000 10%数据N<=6
输出格式
阿申想知道不出现不吉利数字的号码有多少种,输出模 K 取余的结果。
输入输出样例
输入 #1
4 3 100 111
输出 #1
81
我尽力了,但它就是过不了,我能怎么办(切紫题又不是切西瓜······)
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int N=1e2+5; int net[N],n,m,a[N][N],mod; struct ch { static const int M=21; int a[M][M]; ch() {memset(a,0,sizeof(a));} ch operator*(ch b) { ch c; for(int i=0;i<M;++i) { for(int j=0;j<M;++j) { for(int k=0;k<M;++k) c.a[i][j]+=a[i][k]*b.a[k][j],c.a[i][j]%=mod; } } return c; } ch& operator*=(ch b) { *this=*this*b; return *this; } ch operator^(int k) { ch base=*this,ans; for(int i=0;i<M;++i) ans.a[i][i]=1; while(k) { if(k&1) { ans*=base; } base*=base; k>>=1; } return ans; } ch operator^=(int k) { *this=*this^k; return *this; } }ans,res; void gg(char* P) { net[0]=0;net[1]=0; for(int i=1;i<m;i++) { int j=net[i]; while(j&&P[i]!=P[j])j=net[j]; net[i+1]=P[i]==P[j]?j+1:0; } } void p(char* P) { for(int i=0;i<m;++i) for(int j=0;j<=9;++j) { int k=i; while(k&&P[k+1]!=j+'0')k=net[k]; if(P[k+1]==j+'0')k++; if(k<m)res.a[i][k]++; } } int main() { scanf("%d%d%d",&n,&m,&mod); char T[N]; scanf("%s",T+1); gg(T); p(T); res=res^n; ans.a[0][0]=1; ans*=res; ll sum; for(int i=0;i<21;i++){ sum+=ans.a[0][i]; sum%=mod; } printf("%d",sum); return 0; }