【BZOJ1152】歌唱王国(生成函数,KMP)

【BZOJ1152】歌唱王国(生成函数,KMP)

题面

BZOJ
洛谷

题解

根据\(YMD\)论文来的QwQ。
首先大家都知道普通型生成函数是\(\displaystyle \sum_{i=0}^{\infty}a_ix^i\),类似的定义概率生成函数\(\displaystyle F(x)=\sum_{i=0}^\infty P(X=i)x^i\)。其中\(P(X=i)\)表示\(X\)这个随机变量为\(i\)的概率。
那么我们可以知道几个结论:\(\displaystyle F(1)=\sum_{i=0}^\infty P(X=i)=1\),这个结论很显然。
如果我们要求解期望,显然期望等于\(\displaystyle \sum_{i=0}^{\infty}iP(X=i)\)
我们发现\(\displaystyle F'(x)=\sum_{i=1}^\infty iP(X=i)x^{i-1}\),那么我们要求解的期望就是\(F'(1)\)
回到题目。
我们设\(f_i\)表示终止长度为\(i\)的概率,\(F(x)\)为其概率生成函数,那么要求解的就是\(F'(1)\)
\(g_i\)表示当前长度为\(i\)且还未结束的概率,\(G(x)\)为其普通型生成函数,那么我们可以得到:

\[F(x)+G(x)=1+G(x)x \]

这个式子什么意思呢?首先右侧的\(1+G(x)x\)表示在当前序列后面随机加上一个字符,要加一的愿意是\(g_0=1\)。那么随机加完一个字符后,结束的概率是变成了\(F(x)\),未结束的概率是\(G(x)\),所以得到了这个等式。
\(a_i\)表示\(A[1..i]\)是否是串\(A\)\(border\),那么我们可以得到:

\[G(x)(\frac{1}{m})^Lx^L=\sum_{i=1}^{L}a_iF(x)(\frac{1}{m})^{L-i}x^{L-i} \]

等式左侧的含义是在当前未结束的串的后面直接接上目标串,那么这样一定会结束。
右侧的含义是因为前面的随机串中可能已经匹配了一部分的长度,导致在匹配了一半此时就已经结束了。
那么我们插入了一半就结束了,并且此时我们插入的一定是一段前缀,因此只有可能当这个位置是\(border\)时才可能结束。
那么强制在这个\(border\)时会结束,等价于我们钦定了随机串的最后\(L-i\)位。那么就得到了右边的式子。
我们要求解的东西是\(F'(1)\)
首先第一个式子可以写成:

\[F'(x)+G'(x)=G(x)+G'(x)x \]

化简得到\(F'(1)=G(1)\)
然后令\(x=1\)带入到第二个式子中,可以得到:

\[G(1)=\sum_{i=1}^La_im^i \]

那么只需要\(KMP\)求解\(border\)就行了。

#include<iostream>
#include<cstdio>
using namespace std;
#define MOD 10000
#define MAX 100100
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
int n,T,pw[MAX],s[MAX],nt[MAX];
int main()
{
	n=read();T=read();
	pw[0]=1;for(int i=1;i<MAX;++i)pw[i]=1ll*pw[i-1]*n%MOD;
	while(T--)
	{
		int m=read(),ans=0;
		for(int i=1;i<=m;++i)s[i]=read();
		for(int i=2;i<=m;++i)
		{
			int t=nt[i-1];
			while(t&&s[t+1]!=s[i])t=nt[t];
			if(s[t+1]==s[i])++t;
			nt[i]=t;
		}
		for(int i=m;i;i=nt[i])ans=(ans+pw[i])%MOD;
		printf("%04d\n",ans);
	}
	return 0;
}
posted @ 2019-04-03 15:28  小蒟蒻yyb  阅读(665)  评论(0编辑  收藏  举报