把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P3193 [HNOI2008]GT考试

题面传送门
\(n\)这么大肯定只能矩乘(暴论
但是不能出现这个串的限制很难搞,考虑设\(dp_{i,j}\)表示第\(i\)位然后匹配到答案第\(j\)位。
然后如果预处理出kmp就可以\(O(10nm)\)搞了。
把这个递推改成矩乘就可以\(O(m^3logn)\)轻松跑过。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define lb long db
#define N 20
#define W (1<<31)-1
#define mod 998244353
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Pc(x) putchar(x) 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,p,now,net[N+5],ToT;char S[N+5];
struct matrix{
	int A[N+5][N+5];matrix(){Me(A,0);}
	matrix operator *(matrix &B)const{
		matrix C;re int i,j,h;for(h=0;h<=m;h++){
			for(i=0;i<=m;i++)for(j=0;j<=m;j++) C.A[i][j]=(C.A[i][j]+A[i][h]*B.A[h][j])%p;
		}return C;
	} 
}Ans,Bas;
int main(){
	//freopen("1.in","r",stdin);
	re int i,j;scanf("%d%d%d",&n,&m,&p);scanf("%s",S+1);for(i=1;i<=m;i++) S[i]-='0';for(i=1;i<=m;i++){net[i]=net[i-1];while(net[i]&&S[net[i]+1]^S[i])net[i]=net[net[i]];net[i]+=(i^1&&S[net[i]+1]==S[i]);}
	for(i=0;i<m;i++){
		for(j=0;j<=9;j++){
			now=i;while(now&&S[now+1]^j) now=net[now];now+=(S[now+1]==j);Bas.A[i][now]++;
		}
	}Ans.A[0][0]=1;while(n)n&1&&(Ans=Ans*Bas,0),n>>=1,Bas=Bas*Bas;for(i=0;i<m;i++) ToT+=Ans.A[0][i];printf("%d\n",ToT%p);
}
posted @ 2021-08-24 14:49  275307894a  阅读(36)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end