bzoj5130 字符串的周期(kmp,最小表示法)

bzoj5130 字符串的周期(kmp,最小表示法)

bzoj

题解时间

m很大,n很小。

周期很容易求,就是kmp之后n-fail[n]。

之后对于枚举所有的字符串用最小表示法,暴力搜索。

能过就完事了。

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operator<(const pat &p)const{return x==p.x?y<p.y:x<p.x;}};
template<typename TP>inline void read(TP &tar)
{
	TP ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();}
	tar=ret*f;
}
namespace RKK
{
const int N=20,mo=998244353;
void doadd(lint &a,lint b){if((a+=b)>=mo) a-=mo;}

int n;lint m;
int s[N],fail[N];
lint am[N];
lint ans;
void dfs(int dep,int cnt)
{
	if(dep==n)
	{
		// cerr<<"sora"<<endl;
		lint tmp=1;
		for(int i=2,j=0;i<=n;i++)
		{
			while(j&&s[j+1]!=s[i]) j=fail[j];
			fail[i]=s[j+1]==s[i]?++j:j;
			(tmp*=(i-j))%=mo;
			// cerr<<tmp<<endl;
		}
		doadd(ans,tmp*am[cnt]%mo);return;
	}
	for(int i=1;i<=cnt;i++) s[dep+1]=i,dfs(dep+1,cnt);s[dep+1]=cnt+1,dfs(dep+1,cnt+1);
}

int main()
{
	#ifdef RDEBUG
	freopen("sample.in","r",stdin);
	#endif
	read(n),read(m);am[0]=1;for(int i=1;i<=n;i++) am[i]=am[i-1]*(m-i+1)%mo;
	dfs(0,0);printf("%lld\n",ans);
	return 0;
}
}
int main(){return RKK::main();}
posted @ 2020-05-07 22:34  RikukiIX  阅读(232)  评论(0编辑  收藏  举报