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;
}