Luogu4548 歌唱王国

Luogu4548 歌唱王国

题面:Luogu

解析

很有趣的一道题目。

考虑一类生成函数,对于一个离散的整型随机变量\(t\),该函数的每一项\(x^i\)的系数表示该变量取值为\(i\)的概率,也就是:

\[f(x)=\sum_{i=0}^{\infty} P(t=i)x^i \]

这个函数有一些有趣的性质,例如:\(f(1)=1\)
以及对于\(t\)的期望有:\(E(t)=f'(1)\)

现在对于这道题目,令\(n\)表示字符集大小,\(m\)表示名字长度。

考虑设\(F(x)\)表示对于在唱第\(i\)个数字结束的概率的生成函数,\(G(x)\)表示对于在唱第\(i\)个数字未结束的概率的生成函数。

显然有下面这个式子:

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

即在未结束的串后再接上一个字符,有可能结束,也可能不结束。

其次,有:

\[G(x) \Big(\frac{1}{n}x\Big)^m=\sum_{i=1}^{m}a_{i}F(x)\Big(\frac{1}{n}x\Big)^{m-i} \]

即在未结束的串后接上名字一定会结束,但在这之前可能会提前结束,其中\(a_{i}=0/1\),表示\(s[1,i]\)是否为串\(s\)\(border\)

对第一个式子求导并化简,有:

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

在第二个式子中带入\(x=1\),有:

\[G(1)=\sum_{i=1}^{m} a_{i} n^{i} \]

所以:

\[E(x)=F'(1)=G(1)=\sum_{i=1}^m a_{i} n^{i} \]

对于\(a_{i}\)\(kmp\)求即可。

代码


#include<cstdio>
#define N 100005

using namespace std;

inline int In(){
	char c=getchar(); int x=0,ft=1;
	for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1;
	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
	return x*ft;
}

const int P=10000;
int n,T,m,s[N],nex[N],pw[N];

int main(){
	n=In(); T=In();
	while(T--){
		m=In(); for(int i=1;i<=m;++i) s[i]=In();
		pw[0]=1; for(int i=1;i<=m;++i) pw[i]=pw[i-1]*n%P;
		for(int i=2,j=0;i<=m;++i){
			while(j&&s[j+1]!=s[i]) j=nex[j];
			if(s[j+1]==s[i]) ++j; nex[i]=j;
		}
		int sum=0;
		for(int i=m;i;i=nex[i]) sum=(sum+pw[i])%P;
		printf("%.4d\n",sum);
	}
	return 0;
}

posted @ 2019-08-24 15:04  pkh68  阅读(136)  评论(0编辑  收藏  举报