题解:AT_abc305_g [ABC305G] Banned Substrings

题目:

\(f_{i,a/b,a/b,a/b,a/b,a/b}\)\(i\) 长度的字符串,且最后五个顺次的字符为这些 \(a/b\) 的方案数。

转移可以直接枚举 \(s_i\),发现转移只与后五位有关,直接上个矩乘就完了。

初始化跑暴力 dfs。

从刷表角度构造矩阵即可。自己推

#include<bits/stdc++.h>
using namespace std;
#define ll long long
void xie(int x,int shen=1)
{
	if(shen>6) return ;
	xie(x/2,shen+1);
	putchar('0'+x%2);
	if(shen==1) putchar('\n');
}
const int QAQ=130,ovo=33;
const ll mo=998244353;
string s[QAQ];
ll n;
int a[QAQ][8],m,len[QAQ],xian;
int ya[QAQ],no[9][QAQ];
int jie(int xian,int l,int r)
{
	xian>>=(l-1);
	
	xian&=((1<<(r-l+1))-1);//
	return xian;
}
int bx[QAQ];
void yln()
{
	for(int s=0;s<(1<<6);s++)
	{
		int emm=1;
		for(int l=1;l<=6&&emm;l++)
			for(int r=l;r<=6&&emm;r++)
				if(no[r-l+1][jie(s,l,r)]) emm=0;
		if(!emm) bx[s]=1;
//		,xie(s);
	}
}
int f[8][QAQ],U;
void dfs(int x,int xian)
{
//	cout<<x<<'\n';
	int emm=1;
	for(int l=1;l<=x-1&&emm;l++)
		for(int r=l;r<=x-1&&emm;r++)
			if(no[r-l+1][jie(xian,l,r)]) emm=0;
//	if(!emm) cout<<"wocao";
	f[x-1][xian]+=emm;
	if(x>5) return ;
	
	xian<<=1;
	xian&=U;
	dfs(x+1,xian|1);
	dfs(x+1,xian);
}
#define jia(x,y) (x=((x)+(y))%mo)
vector<int> to[ovo];
struct xxx
{
	ll jz[ovo][ovo];
	void csh()
	{
		for(int i=0;i<=31;i++)
			for(int j=0;j<=31;j++)
				jz[i][j]=0;
	}
	void dw()
	{
		csh();
		for(int i=0;i<=31;i++)
			jz[i][i]=1;
	}
} zy,nw;
xxx operator *(xxx a,xxx b)
{
	xxx c;c.csh();
	for(int i=0;i<=31;i++)
		for(int j=0;j<=31;j++)
			for(int k=0;k<=31;k++)
				jia(c.jz[i][j],a.jz[i][k]*b.jz[k][j]);
	return c;
}
xxx ksm(xxx x,ll k)
{
	xxx da;
	da.dw();
	for(;k;k/=2,x=x*x) if(k%2==1) da=da*x;
	return da;
}
void roxy()
{
	zy.csh();
	for(int i=0;i<=31;i++)
		for(int v:to[i])
			zy.jz[i][v]=1;
	for(int i=0;i<=31;i++) nw.jz[0][i]=f[5][i];
//	,cout<<f[5][i]<<" ";
}
signed main()
{
//	freopen("shuju.in","r",stdin);
//	freopen("wode.out","w",stdout);
	cin>>n>>m;
	for(int i=0;i<5;i++) U|=(1<<i);
	for(int i=1;i<=m;i++) cin>>s[i],len[i]=s[i].size();
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=len[i];j++)
		{
			a[i][j]=s[i][j-1]-'a';
			ya[i]=(ya[i]<<1);
			if(s[i][j-1]=='b') ya[i]|=1;
		}
		no[len[i]][ya[i]]=1;
	}
	dfs(1,0);
	yln();
	
	for(int s=0;s<32;s++)
	{
		if(!bx[(s<<1)|1]) to[s].push_back(((s<<1)&U)|1);
		if(!bx[s<<1]) to[s].push_back(((s<<1)&U));
	}
	if(n<=4)
	{
		int ans=0;
		for(int s=0;s<32;s++) jia(ans,f[n][s]);
		cout<<ans;
		return 0;
	}
//	for(int i=1;i<=n;i++) cout<<
	
	roxy();
	nw=nw*ksm(zy,n-5);
	
	int ans=0;
	for(int s=0;s<32;s++) jia(ans,nw.jz[0][s]);
	cout<<ans;
	return 0;
}
posted @ 2025-10-03 21:29  _a1a2a3a4a5  阅读(9)  评论(0)    收藏  举报