zoukankan      html  css  js  c++  java
  • 概率生成函数学习笔记

    哪个天才把多项式出到概率上的啊

    性质

    设一个多项式 (F(x)=sum P(X=i)x^i)

    然后会发现这玩意有一堆性质,然后就被出成题了。。。

    • (F(1)=1) 。这个显然,所有情况的概率和就是 (1)(sum P(X=i)=1)
    • (E(X)=F'(1))

    (E(X)=sum i imes P(X=i)) 带系数,怎么搞?求个导,就有 (i) 了。

    • (E(X^{underline k})=F^{(k)}(1))(k) 阶导)。

    上面那个式子多求几次导即可。

    或许有人和我一样不知道 (E(X^{underline{k}})) 是啥意思。。。(E(X^{underline{k}})=sum P(X=i)i^{underline{k}})

    • (E(X^2)=F''(x)+F'(x))

    (E(X^2)=E(X^{underline{2}}+X^{underline{1}})=E(X^{underline{2}})+E(X^{underline{1}})=F''(x)+F'(x))

    • 方差 (V(X)=F''(1)+F'(1)-F'(1)^2)

    (V(x)=E(X^2)-E(X)^2=F''(1)+F'(1)-F'(1)^2)

    • 补充一下 (V(X)=E(X^2)-E(X)^2) 是怎么推出来的,我自己想了好久,最后是在别人的提醒下翻了《具体数学》第八章明白的。

    [V(X)=E((X-E(X))^2)\ =E(X^2-2XE(X)+E(X)^2)\ =E(X^2)+E(X)^2-2E(X)E(X) ]

    主要是上面那步理解了好久,因为 (E(X)) 是个常数,所以 (E(E(X)^2)=E(X)^2) 被直接提了出来。(E(X E(X))=E(X)E(E(X))=E(X)^2) ,这个用期望的线性性+乘法分配律即证。

    [=E(X^2)-E(X)^2 ]

    所以,方差等于“随机变量平方的均值减去其均值的平方”

    然后就可以做题了。。。


    例1

    P4548 [CTSC2006]歌唱王国

    好像是个套路,但是真的nb

    ([x^n]F(x)) 为第 (n) 轮恰好唱出一个名字的概率,([x^n]G(x)) 表示 (n) 轮之后还没有唱出名字的概率。

    那么

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

    上一轮如果还得接着唱,那么再唱一轮只可能结束或者没结束。后面那个 (1) 就是你唱了 (0) 轮必然唱不出名字,然而因为 (G(x)) 乘了 (x) 常数项没了要手动补上。怎么感觉是废话,但是这个式子很有用

    首先,根据上面性质那部分推导,我们要求的是 (F'(1))

    上面那个式子两边求导

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

    直接把 (x=1) 带进去

    (F'(1)=G(1))

    所以只要求 (G(1)) 就行了。

    还有一波骚操作可以导出 (F(x),G(x)) 的关系。

    考虑如何表示出一个必然结束的情况。

    (G(x)) 来写就是 (G(x)(dfrac{x}{n})^{m}) ,也就是暴力在后面接上一个名字。

    但是有可能会存在提前结束的情况。

    非常神奇的是用 (F(x)) 能写出一个有相同组合意义的式子,所以并不用管提前结束这玩意。

    显然,(G(x)) 那个式子有可能提前结束当且仅当现在这个串的末尾是原串的 ( m Border)

    事实上这东西并不严格是 ( m Border) ,因为 ( m Border) 不能等于自身,但是这题可以。能懂就好了qwq

    (A_i) 表示 ([S[1,cdots,i]=S[m-i+1,m]]) 也就是是否为 ( m Border)

    [sum_{i=1}^{m}A_iF(x)(dfrac{x}{n})^{m-i} ]

    后面那个幂次是补上剩下的操作。其实可以理解成枚举在哪个位子提前结束。

    所以现在我们得到的是

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

    带入 (x=1)

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

    再用性质里头那个 (F(1)=1) ,两边同时乘 (n^m) 得到

    [G(1)=sum_{i=1}^{m}A_in^i ]

    感觉好牛逼啊,第一次把具体值往生成函数里代诶。

    关于怎么求 (A_i) ,记住一句曾经在我们班广泛流传的一句话:( m Border)( m Border)( m Border) 。很有用的(

    const int N=100005;
    #define mod 10000
    void fmod(int&x){x-=mod,x+=x>>31&mod;}
    int n,m,p[N],a[N],ans;
    bool A[N];
    void print(int n){
       int d[5];d[0]=0;
       for(;n;n/=10)d[++d[0]]=n%10;
       while(d[0]<4)d[++d[0]]=0;
       while(d[0])printf("%c",'0'+d[d[0]--]);
       puts("");
    }
    signed main(){
       n=read();
       for(int T=read();T;--T){
       	m=read(),ans=0;
       	rep(i,1,m)a[i]=read(),A[i]=0;
       	p[1]=0;
       	int j=0;
       	for(int i=2;i<=m;++i){
       		while(j&&a[j+1]!=a[i])j=p[j];
       		if(a[j+1]==a[i])++j;
       		p[i]=j;
       	}
       	j=m;
       	while(j)A[j]=1,j=p[j];
       	for(int i=1,j=n;i<=m;++i,j=1ll*j*n%mod)if(A[i])fmod(ans+=j);
       	print(ans);
       }
    }
    

    例2

    P3706 [SDOI2017]硬币游戏

    ([x^n]G(x)) 表示 (n) 轮之后仍未结束的概率。

    考虑答案怎么表示。不能像上面只开一个了。但是注意到 (n) 很小,于是可以开 (n) 个。

    ([x^n]F_{i}(x)) 表示第 (i) 个人在第 (n) 轮获胜的概率。

    和上一题一样,考虑搞一个必然结束的式子出来:

    [G(x)(dfrac{x}{2})^{m} ]

    随便在后面接一个串就好了,不妨接上第 (i) 个。

    对于 (F_i(x)) 可以列一个和上面组合意义相同的式子。

    [sum_{j=1}^{n}sum_{k=1}^{m}A_{i,j,k}F_j(x)(dfrac{x}{2})^{m-k} ]

    其中 (A_{i,j,k}=[S_i[1,cdots,k]=S_j[m-k+1,cdots,m]]) 可以哈希 (O(n^3)) 搞。

    还是在枚举在哪个地方出现了提前结束的情况。

    所以对于每一个 (iin[1,n]) 都有

    [G(x)(dfrac{x}{2})^{m}=sum_{j=1}^{n}sum_{k=1}^{m}A_{i,j,k}F_j(x)(dfrac{x}{2})^{m-k} ]

    还有一个式子是

    [G(x)+sum_{i=1}^{n}F_i(x)=xG(x)+1 ]

    比较显然不解释了。

    我们要求的是所有的 (F_i(1))

    (x=1) 带入第二个式子

    [sum_{i=1}^{n}F_i(1)=1 ]

    然后把第一个式子两边带入 (x=1)

    [G(1)(dfrac{1}{2})^m=sum_{j=1}^{n}sum_{k=1}^{m}A_{i,j,k}F_j(1)(dfrac{1}{2})^{m-k}\ G(1)=sum_{j=1}^{n}sum_{k=1}^{m}A_{i,j,k}F_j(1)2^k ]

    (n+1) 个未知数 (n+1) 个方程直接高消就好了。

    但是 (2^{300}) 次方是啥玩意啊。然后我去看了看题解区有什么高妙做法

    woc这玩意double居然能存,存完还能高消,怎么这么nb啊,而且我还不会卡诶(

    woc为啥题解都能跑,我就被卡精度了啊/kk

    woc我为啥 (2^{300}) 开的是 int 啊,手残手残,我是傻逼。。。然后就过了qwq

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mkp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define sz(v) (int)v.size()
    typedef long long LL;
    typedef double db;
    template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
    template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
    #define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
    #define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    const int N=305;
    #define mod1 998244353
    #define mod2 1000000007
    #define base1 31
    #define base2 37
    int n,m,H1[N][N],H2[N][N],pw1[N],pw2[N];
    db a[N][N],ans[N],pw[N];
    int hash1(int id,int l,int r){
    	return (H1[id][r]-1ll*H1[id][l-1]*pw1[r-l+1]%mod1+mod1)%mod1;
    }
    int hash2(int id,int l,int r){
    	return (H2[id][r]-1ll*H2[id][l-1]*pw2[r-l+1]%mod2+mod2)%mod2;
    }
    void Gauss(int n){
    	rep(i,1,n){
    		int mx=i;
    		rep(j,i,n)if(fabs(a[j][i])>fabs(a[mx][i]))mx=j;
    		if(mx!=i)rep(j,1,n+1)swap(a[mx][j],a[i][j]);
    		rep(j,1,n){
    			if(i==j)continue;
    			db div=a[j][i]/a[i][i];
    			rep(k,i,n+1)a[j][k]-=a[i][k]*div;
    		}
    	}
    	rep(i,1,n)ans[i]=a[i][n+1]/a[i][i];
    }
    signed main(){
    	n=read(),m=read();
    	pw[0]=pw1[0]=pw2[0]=1;
    	rep(i,1,m)pw1[i]=1ll*pw1[i-1]*base1%mod1,pw2[i]=1ll*pw2[i-1]*base2%mod2,pw[i]=2.*pw[i-1];
    	rep(i,1,n){
    		static char str[N];scanf("%s",str+1);
    		rep(j,1,m)H1[i][j]=(1ll*H1[i][j-1]*base1+(str[j]=='H')+1)%mod1,H2[i][j]=(1ll*H2[i][j-1]*base2+(str[j]=='H')+1)%mod2;
    	}
    	rep(i,1,n){
    		db res=0;
    		rep(j,1,n)rep(k,1,m)
    			if(hash1(i,1,k)==hash1(j,m-k+1,m)&&hash2(i,1,k)==hash2(j,m-k+1,m))a[i][j]+=pw[k];
    		a[i][n+1]=-1,a[i][n+2]=0;
    	}
    	rep(i,1,n)a[n+1][i]=1;a[n+1][n+1]=0,a[n+1][n+2]=1;
    	Gauss(n+1);
    	for(int i=1;i<=n;++i)printf("%.10lf
    ",ans[i]);
    	return 0;
    }
    

    预告:可能还会有道例题,等我会做了再放上来。。。

    upd:例题没了,因为我不会做。

  • 相关阅读:
    poj2240
    poj1135
    poj1062
    poj3278
    2218 补丁vs错误
    必做: 1041、1024、1077、2218、1183(较难)
    poj2828
    poj3253
    洛谷P1122 最大子树和
    1074 食物链
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14256844.html
Copyright © 2011-2022 走看看