• CTSC2006 歌唱王国


    歌唱王国

    problem

    题解

    (f_i) 表示 (i) 步结束的概率,(g_i) 表示 (i) 步未结束的概率。

    [g_i=f_{i+1}+g_{i+1}\ g_i(frac{1}{m})^L=sum_{j>i 且 j-i是 ext{border}} f_j (frac{1}{m})^{L-(j-i)} ]

    第一个转移表示掷一次骰子dice会发生的事情。

    第二个转移表示拼一个原串上去会发生的事情。(一定会结束)

    solution1

    solution2

    https://jkloverdcoi.github.io/2019/12/13/bzoj-1152-歌唱王国/
    https://www.cnblogs.com/cjyyb/p/10649150.html

    要求的是 (F’(1)) ,将 (1) 式两边对 (x) 求导后代入 (x=1),得到

    [F’(x)+G’(x)=xcdot G’(x)+G(x)\ F’(1)=G(1) ]

    (x=1) 代入 (2) 式,得到

    [G(1)=m^Lsum_{i=1}^n a_icdot F(1) cdot (frac{1}{m})^{L-i}\ G(1)=sum_{i=1}^n a_icdot F(1) cdot m^i\ ]

    注意到 (F(1)=sum f_i=1),所以

    [F’(1)=sum_{i=1}^n a_icdot m^i ]

    于是只需用 KMP 判断给定序列的每个前缀是不是它的 border 就可以了.

    用 %04d 可以达到题目要求的输出效果,当然也可以自己写一下输出.

    时间复杂度 (O(n))

    CO int N=1e5+10;
    int pw[N];
    int str[N],nxt[N];
    
    void real_main(){
    	int n=read<int>();
    	for(int i=1;i<=n;++i) read(str[i]);
    	for(int i=2;i<=n;++i){
    		int j=nxt[i-1];
    		while(j and str[j+1]!=str[i]) j=nxt[j];
    		if(str[j+1]==str[i]) ++j;
    		nxt[i]=j;
    	}
    	int ans=0;
    	for(int i=n;i;i=nxt[i]) ans=add(ans,pw[i]);
    	printf("%04d
    ",ans);
    }
    int main(){
    	int m=read<int>();
    	pw[0]=1;
    	for(int i=1;i<N;++i) pw[i]=mul(pw[i-1],m);
    	for(int T=read<int>();T--;) real_main();
    	return 0;
    }
    

    总结概率生成函数:

    • 优点:处理简洁,易扩展,⽐如可以改成求⽅差,或者说求某⼀项的值。

    • 缺点:列⽅程⽐较不直观,需要⼀定的套路积累和练习(+⼀个/+⼀组)。

  • 相关阅读:
    双栈排序
    Koishi Loves Segments
    [USACO14FEB] Cow Decathlon 牛的十项全能
    [HNOI2016]网络
    koishi的数学题
    邦邦的大合唱站队
    #613(div2)
    Educational Codeforces Round 77
    #Hello 2020
    #601 (Div. 2)
  • 原文地址:https://www.cnblogs.com/autoint/p/12103890.html
Copyright © 2020-2023  润新知