题解:P4548 [CTSC2006] 歌唱王国

link

这是一道神秘的生成函数题,我们首先挖掘概率生成函数的一些性质,其中 \(P(X)\) 表示 \(X\) 事件的概率,\(E(x)\) 表示期望,\(A'\)\(A\) 的导数:

\[A(x)=\sum_{i=0}^\infty P(X=i)x^i \]

\[A'(x)=\sum_{i=0}^\infty iP(X=i)x^{i-1} \]

考虑带入 \(x=1\),则 \(A(1)=1,A'(x)=E(X)\)

正文

考虑设 \(F(x)\)\(i\) 次项表示 \(i\) 次后游戏恰好结束的概率,\(G(x)\) 表示游戏未结束的概率(\(G\) 并不适用上述性质,因为其每个项的系数相当于一个后缀和)。则根据其意义有:

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

这是因为无论第 \(i+1\) 次是否结束,第 \(i\) 次定然没有结束,\(+1\) 是为了补齐常数项。对这个式子两边求导有:

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

代入 \(x=1\),再根据开头分析的性质,有:

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

\[E(X)=F'(1)=G(1) \]

因此我们求解 \(G(1)\) 即可,而我们有 \(F(1)=1\),所以我们要把 \(G(x)\)\(F(x)\) 表示。因此我们需要使得游戏在 \(G(x)\) 之后必须结束,可以在后面拼一个原串,如果设 \(b_i\) 表示 \([1,i]\) 是不是一个 border(原串也被认为是一个 border),原串的长度为 \(n\),字符集的大小为 \(m\),则有:

\[G(x)(\frac1mx)^n = \sum_{i = 1}^nb_iF(x)(\frac1mx)^{n-i} \]

这是因为拼一个原串后可能会提前结束,而结束的位置一定是原串的一个 border。接下来我们把两边同乘 \(m^n\),则有:

\[G(x)x^n=\sum_{i=1}^nb_iF(x)x^{n-i}m^i \]

代入 \(x=1\) 有:

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

KMP 求解即可,时间复杂度 \(O(\sum n)\)

参考资料:题解 P3706 【[SDOI2017]硬币游戏】

Code:

#include<iostream>
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
using namespace std;
const int maxn=1e5+5,mod=1e4;
int s[maxn],nxt[maxn],pw[maxn],o[10];
int main(){
	int in,it;
	cin>>in>>it;
	pw[0]=1;
	rep(v1,1,1e5)pw[v1]=pw[v1-1]*in%mod;
	while(it--){
		int im;
		scanf("%d",&im);
		rep(v1,1,im)scanf("%d",s+v1);
		int cp=0;
		rep(v1,2,im){
			while(cp&&s[cp+1]!=s[v1])cp=nxt[cp];
			if(s[cp+1]==s[v1])cp++;
			nxt[v1]=cp;
		}
		int p=im,ans=0;
		while(p){
			ans=(ans+pw[p])%mod;
			p=nxt[p];
		}
		rep(v1,1,4){
			o[v1]=ans%10;
			ans/=10;
		}
		per(v1,4,1)printf("%d",o[v1]);
		printf("\n");
	}
	return 0;
}
posted @ 2025-03-07 20:20  FugiPig  阅读(9)  评论(0)    收藏  举报