GT考试

题目链接:GT考试


设 dp[i][j] 为第一个串到位置 i ,第二个串到位置 j 的方案数。
然后:dp[i][j] = dp[i][k] * g[k][j] g数组 g[i][j] 表示,从i位置到j的方案数。

然后这个可以ac自动机或者kmp预处理,然后做一个矩阵快速幂即可。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=22;
int n,m,mod,c[N][10],fail[N],idx,ed[N],res; char str[N];
struct mat{int g[N][N];}s,a;
void mul(mat &a,mat b){
	mat c; memset(c.g,0,sizeof c.g);
	for(int i=0;i<=idx;i++)
		for(int j=0;j<=idx;j++)
			for(int k=0;k<=idx;k++)
				c.g[i][j]=(c.g[i][j]+a.g[i][k]*b.g[k][j])%mod;
	a=c;
}
void insert(){
	int p=0;
	for(int i=1;str[i];i++){
		int k=str[i]-'0';
		if(!c[p][k]) c[p][k]=++idx;
		p=c[p][k];
	}
	ed[p]=1;
}
void build(){
	queue<int> q;
	for(int i=0;i<10;i++) if(c[0][i]) q.push(c[0][i]);
	while(q.size()){
		int u=q.front(); q.pop();
		ed[u]|=ed[fail[u]];
		for(int i=0;i<10;i++)
			if(c[u][i]) fail[c[u][i]]=c[fail[u]][i],q.push(c[u][i]);
			else c[u][i]=c[fail[u]][i];
	}
}
signed main(){
	scanf("%d %d %d %s",&n,&m,&mod,str+1);
	insert(),build();
	for(int i=0;i<=idx;i++) for(int j=0;j<10;j++)
		if(!ed[i]&&!ed[c[i][j]])  a.g[i][c[i][j]]++;
	s.g[0][0]=1;
	for(;n;n>>=1,mul(a,a)) if(n&1) mul(s,a);
	for(int i=0;i<=m;i++) res=(res+s.g[0][i])%mod;
	cout<<res;
	return 0;
}
上一篇:ABAP创建动态内表


下一篇:HTML中显示特殊字符,如尖括号 “<”,">"等等