[CTSC2016]歌唱王国

[CTSC2016]歌唱王国

Tags:题解


题意

链接:在空串后不断随机添加字符,直到出现串\(S_i\)为止。求最终串的期望长度。\(\sum |S_i|\le 5*10^6\)

题解

以下内容来自\(YMD\)的2018年集训队论文
很奇怪的生成函数题:
\(f[i]\)表示串最终长度为\(i\)的概率,\(g[i]\)表示到达长度\(i\)还没有结束的概率。分别对应生成函数\(F(x),G(x)\)。最后要求的就是\(F'(1)\)(求导,相当于每个概率都乘上了指数也就是长度,变成了期望)。

会有两个式子:\[G(x)*x+1=F(x)+G(x)\]\[G(x)*(\frac{1}{m}x)^L=\sum_{i=1}^{L}a_iF(x)(\frac{1}{m}x)^{L-i}\]第一个式子:在没有结束的串后随意添加一个字符,可能结束也可能没有结束,+1是为了补齐余项

第二个式子:\(L\)表示\(|S|\)\(m\)是字符集,\((bool)a_i\)表示\(i\)是不是一个\(border\)。在没有结束的串后加\(S\),可能加到第\(i\)个字符就结束了,这个时候要求\(S_{1...i}\)是原串的\(border\)




将第一个式子求导:\[F'(x)+G'(x)=G'(x)*x+G(x)\]\(F'(1)=G(1)\)
\(x=1\)代入第二个式子得\[G(1)(\frac{1}{m})^L=\sum_{i=1}^La_iF(1)(\frac{1}{m})^{L-i}\]又因为\(F(1)=1\)(概率和为1),所以\[F'(1)=G(1)=\sum_{i=1}^{L}a_im^i\]用KMP求每个位置上的\(Border\)就好了

代码

#include<iostream>
using namespace std;
const int N=1e5+10,mod=1e4;
int s[N],v[N],nxt[N],l,n,t;
int main()
{
    cin>>n>>t;v[0]=1;
    for(int o=1;o<=t;o++)
    {
        int l,ans=0;cin>>l;
        for(int i=1;i<=l;i++) scanf("%d",&s[i]),v[i]=v[i-1]*n%mod;
        for(int i=2;i<=l;i++)
        {
            int j=nxt[i-1];
            while(s[i]!=s[j+1]&&j) j=nxt[j];
            nxt[i]=s[i]==s[j+1]?j+1:j;
        }
        for(int p=l;p;p=nxt[p]) (ans+=v[p])%=mod;
        cout<<ans/1000%10<<ans/100%10<<ans/10%10<<ans%10<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/xzyxzy/p/10332566.html