淺談 概率與期望 DP
概率與期望DP,一直都不會啊,感覺好難完全沒法思考…
期望題一般是逆推,當然也有一些是順推,然而現在我只做過一些水得很的期望題,好菜啊…
UVa 11021 麻球繁衍 藍書p140
題解:
現在有k只麻球,每隻麻球都只能活一天,但是可能會在死前爆出0到n-1值麻球,機率分別為
問題轉化為一隻麻球在m天死完的概率,於是我們發現,在第i天死完的機率為生一個蛋的機率乘以(這一個蛋在)第i-1天死完的機率+生兩個蛋的機率乘以(整兩個蛋)在第i-1天死完的機率,也就是一個蛋在i-1天死完的機率乘以一個蛋在i-1天死完的機率。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int T,n,k,m;
const int MAXN=1000+10;
double p[MAXN],dp[MAXN];
double fast_pow(double num,int k){
double now=num;
double ans=1.0;
while(k){
if(k&1) ans*=now;
now*=now;k>>=1 ;
}
return ans;
}
int main(){scanf("%d",&T);
for(register int kase=1;kase<=T;kase++){
scanf("%d%d%d",&n,&k,&m);
for(register int i=0;i<=n-1;i++) scanf("%lf",&p[i]);
dp[0]=0;dp[1]=p[0];
for(register int i=2;i<=m;i++){
dp[i]=0 ;
for(register int j=0;j<=n-1;j++){
dp[i]+=p[j]*pow(dp[i-1],j);
}
}
double ans=fast_pow(dp[m],k);
printf("Case #%d: %0.7lf\n",kase,ans);
}
return 0;
}
UVa 11427 玩紙牌
這道題貌似很水,藍書p141,我自己都寫出來了,就是說我們要求的是一天晚上玩兒停了的概率,那麼我們用1除以這個概率就可以了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int T,n,a,b;
double p,dp[110][110];
int main(){
scanf("%d",&T);
for(register int kase=1;kase<=T;kase++){
scanf("%d/%d %d",&a,&b,&n);
p=(double)a/b;
memset(dp,0,sizeof(dp));
dp[0][0]=1.0;dp[0][1]=0.0;//在地0局,贏0局的概率為1,在第0局,贏1局的概率為0
for(register int i=1;i<=n;i++)
for(register int i=1;i<=n;i++){//一共玩兒的局數應該小於a/b,故j/i<=a/b,即j*b<=i*a
for(register int j=0;j*b<=i*a;j++){
if(j==0){
dp[i][j]=dp[i-1][j]*(1.0-p);
continue;
}
dp[i][j]=dp[i-1][j]*(1.0-p)+dp[i-1][j-1]*p;
}
}
double ans=0.0;
for(register int j=0;j*b<=a*n;j++)
ans+=dp[n][j];
int final=floor(1/ans);
printf("Case #%d: %d\n",kase,final);
}
return 0;
}
POJ 2096
題目大意:
現在有n種bug,有s個子系統,問期望多少次出現bug使得每個系統都有bug並且每個bug至少出現過一次,每次可以出現一種bug,出現概率均等,都為1/n,每次出現的位置(即位於哪個子系統)的概率也均等,都為1/s。
題解:
我們很容易想到用dp[i][j]表示現在的情況,i表示現在收集了n種bug,j表示現在出現在了j個系統中,顯然dp[n][s]時,期望次數為0
顯然dp[i][j]可以從dp[i][j],dp[i+1][j],dp[i][j+1],dp[i+1][j+1]轉移過來,分別表示新出現的bug是舊bug並且出現在舊系統中,新出現的bug是新bug但是出現在舊系統中,新出現的bug之前已經出現過了但是這次出現在了新系統中,和新bug新系統,轉移的概率很顯然,我們把式子列出來之後移項,然後兩邊同時乘以一個n*s,可以化簡運算,顯然答案是dp[0][0]
#include<iostream>
#include<cstdio>
#include<cstring>
double dp[1010][1010];
int n,s;
int main(){
scanf("%d%d",&n,&s);//n個bug,s個系統
double ns=n*s;
dp[n][s]=0.0;
for(register int i=n;i>=0;i--){
for(register int j=s;j>=0;j--){
if(i==n&&j==s) continue;
dp[i][j]=(ns+((n-i)*j*dp[i+1][j]+(n-i)*(s-j)*dp[i+1][j+1]+i*(s-j)*dp[i][j+1]))/(ns-i*j);
}
}
printf("%.4lf",dp[0][0]);
return 0;
}
期望的線性性
首先,什麼是期望?期望就是指一個變數的平均值,當然是加權的,比如這個變數可能是1的概率為百分之五十,可能是2的概率為百分之二十五,可能是5的概率為百分之二十五,那麼期望就是1 *50%+2 *25%+5 *25%
期望具有線性性,期望本來就是描述平均值的,所以一個隨機變數的期望值也就是(x)=Ex
如果現在有個常量,因為他不會變,所有他的期望值為他自己,比如常量c的期望為c,那麼既然如此E(x+c)顯然應該為x的期望值加上c,因為無論如何c都是不變的,所以我們只需要考慮x的期望值就行了,也即可以把x+c當做一個整體,而c這一部分又是不動的,所以我們可以把它提出來,所以E(x+c)=Ex+c,如果是兩個變數的和的期望呢?顯然兩個變數是獨立的,而兩個變數的和是不是應該等於他們兩個變數自己的期望值相加呢?是的,所以E(x+y)=Ex+Ey,如果是乘法呢?顯然如果一個變數乘一個常量的期望值應該可以把常量提出來,因為無論你變數為多少,都要乘這個常量,所以E(x*c)=cEx,當然最後還可以得出E(kx+c)其中k,c為常量,則E(kx+c)=kEx+c
全概率公式:
如果
貌似很顯然,概率為某B事件發生的概率乘以B事件發生了導致A事件發生的概率的求和
條件期望全期望公式:
所以有