概率生成函数
对于菜鸡博主来说好难啊
其一般形式为$F(x)=sumlimits_{i=0}^∞[x==i]x_i$,第i项的系数表示离散变量x取值为i的概率
一般的两个性质:$F(1)=1,E(x)=F'(1)$
这里用$F(x)$表示结束时的串长的概率生成函数,$G(x)$表示到长度到达...而串未结束的概率生成函数,字符串长为len,那么有:
①$F(x)+G(x)=x*G(x)+1$,含义是长度达到x的概率:左边就是字面意思,右边$x*G(x)$表示x-1时未结束的概率,然后加上放的一次
②$frac{1}{m}^{len}*G(x)=sumlimits_{i=1}^{len} isb[i]*frac{1}{m}^{len-i}*F(x)$,其中$isb_i$表示i是否是一个border,整个式子含义是字符串的结束:左边就是在一个没结束的串左边恰好补上所需要的len个字母,右边表示可能正好补了一个border,然后就也结束了
然后开始倒腾这两个式子,我们的目标是捣腾出$F'(1)$,也就是$E(x)$,而直接对①求导就可以得到$F'(x)$与$G(x)$的关系:
$F'(x)-G'(x)=G'(x)*x+G(x)$
$F'(1)=G(1)$
然后直接把$F(1)=1$扔进第二个式子里
$G(1)=sumlimits_{i=0}^n isb_i m^i$
就是这样
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=100005,mod=10000; 6 int T,p,n,pos,ans,num[N],nxt[N],pw[N]; 7 int main() 8 { 9 scanf("%d",&p),pw[0]=1; 10 for(int i=1;i<=100000;i++) 11 pw[i]=pw[i-1]*p%mod; 12 scanf("%d",&T); 13 while(T--) 14 { 15 scanf("%d",&n); 16 for(int i=0;i<n;i++) 17 scanf("%d",&num[i]); 18 for(int i=1,o=0;i<n;i++) 19 { 20 while(o&&num[o]!=num[i]) o=nxt[o]; 21 nxt[i+1]=(num[o]==num[i])?++o:0; 22 } 23 pos=n,ans=0; 24 while(pos) ans=(ans+pw[pos])%mod,pos=nxt[pos]; 25 printf("%04d ",ans); 26 } 27 return 0; 28 }