概率與期望


定義

  • 概率,就是某個隨機事件出現的可能性大小。

  • \(X\) 是一個離散型的隨機變量,可能值為 \(x_1,x_2…\),對應的概率分別為 \(p_1,p_2…\),那么它的期望值為 \(E(x)=\sum_i \limits p_ix_i\)

期望的線性性

\[E(x+y)=E(x)+E(y) \]

證明:

\[E(x+y)=\sum_i \sum_j(i+j)*P(i=x,j=y) \]

\[=\sum_i\sum_ji*P(i=x,j=y)+\sum_i\sum_jj*P(i=x,j=y) \]

\[=\sum_ii*P(i=x)+\sum_jj*P(j=y) \]

\[=E(x)+E(y) \]

進而有:

\[E(ax)=aE(x)\\ \]

\[E(\sum_i a_i x_i)=\sum_i a_i E(x_i)\\ \]

當隨機變量 \(x\)\(y\) 獨立時,有:

\[E(xy)=E(x)E(y) \]

條件概率

我們記 \(p(A|B)\) 表示在已知事件 \(B\) 發生時事件 \(A\) 發生的概率,條件概率可以用以下公式計算:

\[P(A|B)=\frac{P(AB)}{P(B)} \]

其中 \(p(AB)\) 表示事件 \(B\) 和事件 \(A\) 同時發生的概率,\(p(B)\) 表示事件 \(B\) 發生的概率。

貝葉斯公式

由條件概率的計算方法,我們容易得到貝葉斯公式:

\[P(A|B)=\frac{P(B|A)P(A)}{P(B)} \]

全概率公式

如果隨機變量 \(x\)\(k\) 個取值,分別為 \(x_1, x_2,\ldots ,x_k\),那么:

\[p(A)=\sum^{k}_{i=1} {p(A|x=x_i)p(x=x_i)} \]

[CTSC2017]游戲

根據期望的線性性,我們可以單獨計算每個未知的局面的獲勝概率。

\(x\) 是一個未知局面,顯然 \(x\) 獲勝的概率只與 \(x\) 左邊的第一個已知局面 \(l\) 和右邊的第一個已知局面 \(r\) 有關。

記事件 \(X\) 為小 \(P\) 在第 \(x\) 局中獲勝,事件 \(L,R\) 為第 \(l,r\) 獲勝者和已知相符。則需要求的是:

\[P(X|L,R)=\frac{P(L,R|X)\times P(X)}{P(L,R)}\\ \]

\[=\frac{P(L,R|X)\times P(X)}{P(L,R)}\\ \]

\[=\frac{P(L|X)\times P(R|X)\times P(X)}{P(R|L)\times P(L)}\\ \]

\[=\frac{\frac{P(X|L)\times P(L)}{P(X)}\times P(R|X)\times P(X)}{P(R|L)\times P(L)}\\ \]

\[=\frac{P(X|L)\times P(R|X)}{P(R|L)}\\ \]

我們發現一個區間內的分母是一個定值,因此可以將每個區間內的分母提出,即:

\[\sum_{x=l+1}^{r-1}\frac{P(X|L)\times P(R|X)}{P(R|L)}=\frac{\sum_{x=l+1}^{r-1} P(X|L)P(R|X)} {P(R,L)} \]

考慮動態更新答案,因此我們每次只需要查詢一個區間的如上式子即可。

分母直接對每個點建立矩陣 \(f_i=\left [\begin{matrix} {1-q_i}&{q_i}\\ {1-p_i}&{p_i}\\ \end{matrix} \right]\) 線段樹維護區間矩陣乘積即可。

考慮維護分子,設矩陣 \(g_i=\left [\begin{matrix} {0}&{q_i}\\ {0}&{p_i}\\ \end{matrix} \right]\) ,發現 \(P(X|L)P(R|X)\) 寫成矩陣形式后就是 \((\prod_{i=l+1}^{x-1}\limits f_i)\times g_x \times (\prod_{i=x+1}^{r}\limits f_i)\)

考慮維護 \(\sum_{x=l+1}^{r-1}\limits [(\prod_{i=l+1}^{x-1}\limits f_i)\times g_x \times (\prod_{i=x+1}^{r}\limits f_i)]\),設 \(F=\prod_{i=l+1}^{r}\limits f_i\)\(G=\sum_{x=l+1}^{r-1}\limits [(\prod_{i=l+1}^{x-1}\limits f_i)\times g_x \times (\prod_{i=x+1}^{r}\limits f_i)]\)

對於線段樹節點 \(i\),顯然有:

\[F_i=F_{2*i}\times F_{2*i+1}\\ G_i=G_{2*i}\times F_{2*i+1}+F_{2*i}\times G_{2*i+1} \]

點擊查看代碼
#include<bits/stdc++.h>
using namespace std;
int n,m;
char type[3],op[15];
struct mat{
	double a[2][2];
	mat(int _x=1){a[0][0]=a[1][1]=_x;a[0][1]=a[1][0]=0;}
	inline double* operator [](int t){
		return a[t];
	}
	inline void print(){
    	printf("%lf %lf\n",a[0][0],a[0][1]);
    	printf("%lf %lf\n",a[1][0],a[1][1]);
	}
	inline mat operator *(mat b){
		mat res(0);
		for(int i=0;i<2;i++){
			for(int j=0;j<2;j++){
				res[i][j]=(res[i][j]+a[i][0]*b[0][j]);
				res[i][j]=(res[i][j]+a[i][1]*b[1][j]);
			}
		}return res;
	}
	inline mat operator +(mat b){
		mat res(0);
		for(int i=0;i<2;i++){
			for(int j=0;j<2;j++)res[i][j]=a[i][j]+b[i][j];
		}return res;
	}
}f[800005],g[800005];
double p[200005],q[200005];
void build(int l=0,int r=n,int i=1){
	if(l==r){
		f[i][0][0]=1-q[l];f[i][0][1]=q[l];f[i][1][0]=1-p[l];f[i][1][1]=p[l];
		g[i][0][0]=0;g[i][0][1]=q[l];g[i][1][0]=0;g[i][1][1]=p[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,i<<1);build(mid+1,r,i<<1|1);
	f[i]=f[i<<1]*f[i<<1|1];
	g[i]=g[i<<1]*f[i<<1|1]+f[i<<1]*g[i<<1|1];
}
mat F,G;
void query(int fr,int to,int l=0,int r=n,int i=1){
	if(fr>r||to<l)return ;
	if(fr<=l&&to>=r){
		G=G*f[i]+F*g[i];F=F*f[i];
		return ;
	}
	int mid=(l+r)>>1;
	query(fr,to,l,mid,i<<1);query(fr,to,mid+1,r,i<<1|1);
}
map<int,bool> mp;
inline double calc(int l,int r,bool op1,bool op2){
	F=mat(1);G=mat(0);
	query(l+1,r);
	return G[op1][op2]/F[op1][op2];
}
double ans;
int main(){
	scanf("%d%d%s",&n,&m,type);
	scanf("%lf",&p[1]);
	for(int i=2;i<=n;i++)scanf("%lf%lf",&p[i],&q[i]);
	p[0]=1;q[0]=1;++n;
	build();mp[0]=1;mp[n]=0;
	ans=calc(0,n,1,0);
	while(m--){
		int i,c;
		scanf("%s",op);
		if(op[0]=='a'){
			scanf("%d%d",&i,&c);
			auto r=mp.upper_bound(i),l=r;l--;
			ans-=calc(l->first,r->first,l->second,r->second);
			ans+=calc(l->first,i,l->second,c);ans+=calc(i,r->first,c,r->second);mp[i]=c;
		}
		else {
			scanf("%d",&i);
			auto it=mp.find(i),l=it,r=it;l--;r++;
			ans-=calc(l->first,it->first,l->second,it->second);ans-=calc(it->first,r->first,it->second,r->second);
			ans+=calc(l->first,r->first,l->second,r->second);mp.erase(it);
		}printf("%lf\n",ans);
	}

	return 0;
}

方差相關

方差等於平方的期望減去期望的平方

\[Var(x)=\frac{1}{n}\sum_{i=1}^{n}(x_i-\overline{x})^2\\ =\frac{1}{n}\sum_{i=1}^{n}(x_i^2-2\overline{x}*x_i+\overline{x}^2) \]

\[=\frac{\sum_{i=1}^{n} x_i^2}{n}-2\overline{x}*\frac{\sum_{i=1}^{n} x_i}{n}+\frac{\sum_{i=1}^{n} \overline{x}^2}{n} \]

\[=\frac{\sum_{i=1}^{n} x_i^2}{n}-2\overline{x}^2+\overline{x}^2 \]

\[=E(x^2)-E(x)^2 \]

矩形覆蓋

給定一個大小為 \(n*m\) 的矩形,某一些格子上有物品,共有 \(k\) 個物品,現在等概率選一個子矩形,求子矩形內物品個數的方差。

考慮 \(Var(x)=E(x^2)-E(x)^2\),分別求 \(E(x)\)\(E(x^2)\)

\(E(x)\) 較為好求,即統計每一個點的貢獻即可。

\(E(x^2)\) 可以考慮對於每一對點,統計包含它們的矩形的個數,考慮分類討論一下它們是左上右下的關系還是右上左下的關系,掃描線計算一下即可。

【UER #6】逃跑

還是考慮求 \(E(x^2)\)\(E(x)\)

預處理 \(g[t][x][y]\) 表示 \(t\) 時刻從 \((0,0)\) 到達點 \((x,y)\) 的方案數。

\(f[i]\)\(i\) 時刻期望經過的的點數,有:

\[f[i]=(w1+w2+w3+w4)^i-\sum_{j=0}^{i-1}f[j]\times g[i-j][0][0] \]

則 :

\[E(x)=\sum_{i=0}^{n}f[i]\times (w1+w2+w3+w4)^{n-i} \]

考慮統計同時經過的點對數的方式求出 \(E(x^2)\)

\(h[t][x][y]\) 表示在 \(t\) 時間內經過了 \((a,b)\) 並在 \(t\) 時刻到達 \((a+x,b+y)\) 的方案數,有:

\[h[t][x][y]=\sum_{i=0}^{t-1}f(i)\times g[t-i][x][y]-h[i][-x][-y]\times g[t-i][x][y]-h[i][x][y]\times g[t-i][0][0] \]

由於我們統計的是點對,因此 \(\sum_{t=0}^{n}\limits \sum_{x=-n}^{n}\limits \sum_{y=-n}^{n}\limits h[t][x][y]\times (w1+w2+w3+w4)^{n-t}\) 求出的實際上是 \(E(\frac{n\times (n-1)}{2})\)

因此 \(E(x^2)=E(x)+2\times \sum_{t=0}^{n}\limits \sum_{x=-n}^{n}\limits \sum_{y=-n}^{n}\limits h[t][x][y]\times (w1+w2+w3+w4)^{n-t}\)

題目要求 \(Var(x)\times (w1+w2+w3+w4)^n\) ,而 \(\text{std}\) 求的是 \(Var(x)\times (w1+w2+w3+w4)^{2\times n}\)

因此最終輸出應該輸出 \(E(x^2)\times (w1+w2+w3+w4)^n-E(x)^2\)

點擊查看代碼
#include<bits/stdc++.h>
using namespace std;
int n;
long long w1,w2,w3,w4,sum;
const long long md=998244353;
int g[105][205][205],h[105][205][205],f[105],pwr[105];
long long E1,E2;
int main(){
	scanf("%d",&n);
	scanf("%lld%lld%lld%lld",&w1,&w2,&w3,&w4);sum=(w1+w2+w3+w4)%md;
	g[0][n][n]=1;
	for(int t=0;t<n;t++){
		for(int i=0;i<=2*n;i++){
			for(int j=0;j<=2*n;j++){
				if(!g[t][i][j])continue;
	//			cout<<t<<" "<<i<<" "<<j<<" "<<g[t][i][j]<<endl;
				g[t+1][i-1][j]=(g[t+1][i-1][j]+w1*g[t][i][j])%md;
				g[t+1][i+1][j]=(g[t+1][i+1][j]+w2*g[t][i][j])%md;
				g[t+1][i][j-1]=(g[t+1][i][j-1]+w3*g[t][i][j])%md;
				g[t+1][i][j+1]=(g[t+1][i][j+1]+w4*g[t][i][j])%md;
			}
		}
	}
	pwr[0]=1;
	for(int i=1;i<=n;i++)pwr[i]=pwr[i-1]*sum%md;
	for(int i=0;i<=n;i++){
		f[i]=pwr[i];
		for(int j=1;j<=i;j++)f[i]=(f[i]-1ll*f[i-j]*g[j][n][n])%md;
	//	cout<<i<<" "<<f[i]<<endl;
		E1=(E1+1ll*f[i]*pwr[n-i])%md;
	}E2=E1;
	for(int t=0;t<=n;t++){
		for(int i=0;i<=2*n;i++){
			for(int j=0;j<=2*n;j++){
				if(i==n&&j==n)continue;
				for(int k=0;k<t;k++)h[t][i][j]=(h[t][i][j]+1ll*f[k]*g[t-k][i][j]-1ll*h[k][2*n-i][2*n-j]*g[t-k][i][j]-1ll*h[k][i][j]*g[t-k][n][n])%md;
				E2=(E2+2ll*h[t][i][j]*pwr[n-t])%md;
			}
		}
	}
	printf("%lld",((E2*pwr[n]-E1*E1)%md+md)%md);

	return 0;
}

概率生成函數

對於任意取值在非負整數集上的離散隨機變量 \(x\),它的概率生成函數為:

\[F(z)=\sum_{i=0}^{\infty}P(x=i)z^i \]

概率生成函數的一些性質

1.

\[F(1)=\sum_{i=0}^{\infty}P(x=i)=1 \]

2.

\[F'(1)=\sum_{i=0}^{\infty}P(x=i)*i=E(x) \]

3.

\[F^{(k)}(1)=\sum_{i=0}^{\infty}P(x=i)*i^{\underline{k}}=E(x^{\underline{k}}) \]

4.

\[E(x^{k})=E(\sum_{i=0}^{k}\left \lbrace\frac{k}{i}\right\rbrace x^{\underline{i}})=\sum_{i=0}^{k}\left \lbrace\frac{k}{i}\right\rbrace E(x^{\underline{i}})=\sum_{i=0}^{k}\left \lbrace\frac{k}{i}\right\rbrace F^{(i)}(1) \]

[CTSC2006]歌唱王國

\(f[i]\) 表示第 \(i\) 輪結束的概率,\(g[i]\) 表示到了第 \(i\) 輪還沒有的概率。

設生成函數:

\[F(x)=\sum_{i=0}^{\infty}\limits f[i]\cdot x^i,G(x)=\sum_{i=0}^{\infty}\limits g[i]\cdot x^i \]

顯然:

\[f[i]=g[i-1]-g[i] \]

有:

\[F(x)=x\cdot G(x)-G(x) \]

我們考慮在一個長度為 \(i\) 且沒有結束的序列后面生成一個目標序列,直接在序列后面生成的概率是 \(g[i]\times (\frac{1}{n})^m\)

假如目標序列的 \(a_{1\to j}=a_{m-j+1\to m}\),那么我們在長度為 \(i+j\) 且結束了的序列后面插入 \(m-j\) 個字符也可以生成相同的序列,概率為 \(\sum_{j=1}^{m}\limits [a_{1\to j}=a_{m-j+1\to m}]f[i+j]\times (\frac{1}{n})^{m-j}\)

\(kmp[i]=[a_{1\to i}=a_{m-i+1\to m}]\)

有:

\[g[i]\times (\frac{1}{n})^m=\sum_{j=1}^{m}\limits kmp[j]\times f[i+j]\times (\frac{1}{n})^{m-j} \]

進而:

\[G(x)\cdot \left(\frac{x}{n}\right)^m=\sum_{j=1}^{m} kmp[j]\times F(x)\cdot \left(\frac{x}{n}\right)^{m-j} \]

\(F(x)=x\cdot G(x)+G(x)\) 求導可得:

\[F'(x)=G(x)+x\cdot G'(x)-G'(x) \]

\(x=1\),有:

\[F'(1)=G(1)+G'(1)-G'(1)=G(1) \]

聯合第二個方程,有:

\[F'(1)\cdot \left(\frac{1}{n}\right)^m=G(1)\cdot \left(\frac{1}{n}\right)^m=\sum_{j=1}^{m} kmp[j]\cdot F(1)\cdot \left(\frac{1}{n}\right)^{m-j}\\ F'(1)=\sum_{j=1}^{m} kmp[j]\cdot n^j\\ \]

點擊查看代碼
#include<bits/stdc++.h>
using namespace std;
int n,t,m;
int a[100005],nxt[100005],pwr[100005];
const int md=10000;
int main(){
	scanf("%d%d",&n,&t);
	pwr[0]=1;
	for(int i=1;i<=1e5;i++)pwr[i]=pwr[i-1]*n%md;
	while(t--){
		scanf("%d",&m);
		for(int i=1;i<=m;i++)scanf("%d",&a[i]);
		for(int i=2,j=0;i<=m;i++){
			while(j&&a[i]!=a[j+1])j=nxt[j];
			if(a[i]==a[j+1])j++;
			nxt[i]=j;
		}int ans=0;
		for(int i=m;i;i=nxt[i])ans=(ans+pwr[i])%md;
		if(ans<1000)printf("0");
		if(ans<100)printf("0");
		if(ans<10)printf("0");
		printf("%d\n",ans);
	}

	return 0;
}

Dice

有一個 \(m\) 面的骰子,求扔連續 \(n\) 次相同就結束的期望步數和扔連續 \(n\) 次結果不同就結束的期望步數。

對於第一問,可以列出:

\[\begin{cases} F(x)=x\cdot G(x)-G(x)\\ \\ G(x)\cdot (\frac{x}{m})^{n-1}=\sum_{i=1}^{n}\limits F(x)\cdot (\frac{x}{m})^{n-i} \end{cases} \]

有:

\[F'(1)=G(1)\to F'(1)\cdot \left(\frac{1}{m}\right)^{n-1}=\sum_{i=1}^{n}\limits F(1)\cdot \left(\frac{1}{m}\right)^{n-i} \]

解得:

\[F'(1)=\sum_{i=1}^{n}\limits m^{i-1}=\frac{m^n-1}{m-1} \]

第二問:

\[\begin{cases} F(x)=x\cdot G(x)-G(x)\\ \\ G(x)\cdot (\frac{x}{m})^{n}\cdot m^{\underline{n}}=\sum_{i=1}^{n}\limits F(x)\cdot (\frac{x}{m})^{n-i}\cdot (m-i)^{\underline{n-i}} \end{cases} \]

有:

\[F'(1)=G(1)\to F'(1)\cdot(\frac{1}{m})^{n}\cdot m^{\underline{n}}=\sum_{i=1}^{n}\limits F(1)\cdot (\frac{1}{m})^{n-i}\cdot (m-i)^{\underline{n-i}} \]

解得:

\[F'(1)=\sum_{i=1}^{n}\limits \frac{m^{i}}{m^{\underline{i}}} \]

例題

CF1187F Expected Square Beauty

點擊查看代碼
#include<bits/stdc++.h>
using namespace std;
int n;
int l[200005],r[200005];
const long long md=1e9+7;
long long R[200005],pre[200005],suf[200005];
inline long long pwr(long long x,long long y){
	long long res=1;
	while(y){
		if(y&1)res=res*x%md;
		x=x*x%md;y>>=1;
	}return res;
}
long long ans;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&l[i]);
	for(int i=1;i<=n;i++)scanf("%d",&r[i]);
	for(int i=0;i<n;i++){
		int len=max(0,min(r[i],r[i+1])-max(l[i],l[i+1])+1);
		R[i]=(1-len*pwr(r[i]-l[i]+1,md-2)%md*pwr(r[i+1]-l[i+1]+1,md-2))%md;
	}
	for(int i=0;i<n;i++)pre[i]=(pre[i-1]+R[i])%md;
	for(int i=n-1;~i;i--)suf[i]=(suf[i+1]+R[i])%md;
	for(int i=2;i<n;i++)ans=(ans+R[i]*pre[i-2])%md;
	for(int i=0;i<n;i++)ans=(ans+R[i]*suf[i+2])%md;
	for(int i=0;i<n;i++)ans=(ans+R[i])%md;
	for(int i=0;i+1<n;i++){
		int len=max(0,min(r[i],min(r[i+1],r[i+2]))-max(l[i],max(l[i+1],l[i+2]))+1);
		ans=(ans+2*(R[i]+R[i+1]-1+len*pwr(r[i]-l[i]+1,md-2)%md*pwr(r[i+1]-l[i+1]+1,md-2)%md*pwr(r[i+2]-l[i+2]+1,md-2)%md)%md)%md;
	}
	printf("%lld",(ans+md)%md);

	return 0;
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM