CF177G

可能更好的阅读体验

模拟赛题,记录一下。

\(k\le 29\) 时直接 ACAM 即可(这一步实际上是最后得到的),下面考虑 \(k>29\) 的情况。

\(F_{i,j}\) 表示 \(s_j\)\(f_i\) 中的出现次数。

\(F_{i,j}=F_{i-1,j}+F_{i-2,j}+k_{i,j}\),则 \(k_{i,j}\)\(f_{i-1}\) 的一个后缀拼上 \(f_{i-2}\) 的一个前缀得到 \(s_j\) 的次数。

于是只需要关心 \(f_i\) 的最前和最后的 \(100000\) 个字符。

容易计算得到 \(fib_{26}\ge100000\),不难发现 \(i\ge26\)\(f_i\) 的最前 \(100000\) 个字符保持不变,\(i\ge28\)\(f_i\) 的最后 \(100000\) 个字符与 \(f_{i-2}\) 相同。

于是可得 \(i\ge28\)\(k_{i,j}=k_{i-2,j}\),那么矩阵快速幂即可,关键在于求 \(F_{26,j},F_{27,j},k_{28,j},k_{29,j}\),使用 ACAM 求出 \(F_{26,j},F_{27,j},F_{28,j},F_{29,j}\) 即可。

时间复杂度 \(O(\sum\lvert s\rvert+q\log n)\),但是建自动机的时候不优化也能过?

#include<bits/stdc++.h>
using namespace std;
namespace ax_by_c{
typedef long long ll;
const int mod=1e9+7;
const int QQ=1e5+5;
const int M=35;
const int L=514229+5;
const int LS=1e5+5;
char str[M][L];
int len[M];
void Init(){
	len[1]=1;
	str[1][1]='a';
	len[2]=1;
	str[2][1]='b';
	for(int i=3;i<=29;i++){
		len[i]=len[i-1]+len[i-2];
		for(int j=1;j<=len[i-1];j++){
			str[i][j]=str[i-1][j];
		}
		for(int j=1;j<=len[i-2];j++){
			str[i][len[i-1]+j]=str[i-2][j];
		}
	}
}
ll n;
int q,pos[QQ];
char s[LS];
int idx,son[LS][2];
int ins(){
	int u=0;
	for(int i=1;s[i];i++){
		if(!son[u][s[i]-'a'])son[u][s[i]-'a']=++idx;
		u=son[u][s[i]-'a'];
	}
	return u;
}
queue<int>Q;
int nxt[LS],lst[LS],id;
void bld_acam(){
	Q.push(0);
	while(Q.size()){
		int u=Q.front();
		Q.pop();
		lst[++id]=u;
		for(int i=0;i<=1;i++){
            if(!u){
                if(son[u][i])Q.push(son[u][i]);
                continue;
            }
			if(son[u][i]){
				nxt[son[u][i]]=son[nxt[u]][i];
				Q.push(son[u][i]);
			}
            else son[u][i]=son[nxt[u]][i];
		}
	}
}
int cnt[LS],f26[QQ],f27[QQ],f28[QQ],f29[QQ];
void mch(int n){
	for(int i=0;i<=idx;i++)cnt[i]=0;
	int u=0;
	for(int i=1;i<=len[n];i++){
        u=son[u][str[n][i]-'a'];
		cnt[u]++;
	}
	for(int i=idx+1;i>=1;i--)cnt[nxt[lst[i]]]+=cnt[lst[i]];
}
struct matr{
	int n,m;
	int a[3][3];
	void clr(){
		for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
		a[i][j]=0;
	}
};
matr operator * (const matr& a,const matr& b){
	matr c;
	c.n=a.n;
	c.m=b.m;
	c.clr();
	for(int i=0;i<a.n;i++){
		for(int j=0;j<a.m;j++){
			for(int k=0;k<b.m;k++){
				c.a[i][k]=(c.a[i][k]+(ll)a.a[i][j]*b.a[j][k]%mod)%mod;
			}
		}
	}
	return c;
}
matr operator ^ (matr a,ll b){
	matr r=a;
	b--;
	while(b){
		if(b&1){
			r=r*a;
		}
		a=a*a;
		b>>=1;
	}
	return r;
}
void main(){
	Init();
	scanf("%lld %d",&n,&q);
	for(int i=1;i<=q;i++){
		scanf("%s",s+1);
		pos[i]=ins();
	}
	bld_acam();
	if(n<=29){
		mch(n);
		for(int i=1;i<=q;i++){
			printf("%d\n",cnt[pos[i]]);
		}
	}
	else{
		mch(26);
		for(int i=1;i<=q;i++)f26[i]=cnt[pos[i]];
		mch(27);
		for(int i=1;i<=q;i++)f27[i]=cnt[pos[i]];
		mch(28);
		for(int i=1;i<=q;i++)f28[i]=cnt[pos[i]];
		mch(29);
		for(int i=1;i<=q;i++)f29[i]=cnt[pos[i]];
		matr g0,g1,S,gg;
		g0.n=3;
		g0.m=3;
		g0.clr();
		g0.a[1][0]=1;
		g0.a[0][1]=1;
		g0.a[1][1]=1;
		g0.a[2][2]=1;
		g1.n=3;
		g1.m=3;
		g1.clr();
		g1.a[1][0]=1;
		g1.a[0][1]=1;
		g1.a[1][1]=1;
		g1.a[2][2]=1;
		S.n=1;
		S.m=3;
		for(int i=1;i<=q;i++){
			g0.a[2][1]=((ll)f28[i]-f27[i]-f26[i]+mod*2)%mod;
			g1.a[2][1]=((ll)f29[i]-f28[i]-f27[i]+mod*2)%mod;
			S.a[0][0]=f28[i];
			S.a[0][1]=f29[i];
			S.a[0][2]=1;
			gg=g0*g1;
			gg=gg^((n-29)/2);
			S=S*gg;
			if(n%2==0)S=S*g0;
			printf("%d\n",S.a[0][1]);
		}
	}
}
}
int main(){
	ax_by_c::main();
	return 0;
}
posted @ 2024-11-16 14:41  ax_by_c  阅读(11)  评论(0)    收藏  举报