紫书学习 10.数学概念与方法--离散概率基础
作者:互联网
古典概型及其应用
古典概型满足有限性和等可能性,常见的模型是抛硬币。
不求同年同月同日生
有n个人,求至少有两个人生日相同的概率。
每个人的生日有365种可能,因此样本的容量是\(365^n\)。
可以想到暴力的统计方法,恰好两人生日相同、恰好3人....恰好n人生日相同,相加即可,这样比较麻烦。
可以用间接法,先计算任意两个人生日都不相同的概率,再用1减去即可。
\[P=1-\frac{A_{365}^{n}}{365^n} \]注意这里的n如果超过365,根据抽屉原理,就必然存在两个人生日相同了。
条件概率及其应用
条件概率公式如下:
\[P(A|B)=\frac{P(AB)}{P(B)} \]其中,\(P(A|B)\)表示事件A在事件B的条件下发生的概率,\(P(AB)\)表示A,B同时发生的概率,\(P(B)\)表示B发生的概率。
应用:Probability|Given - UVA 11181 - Virtual Judge (vjudge.net)
大意:有n个人走进一家商店,每个人会买东西的概率是\(p_i\),最后有r个人买了东西,求出第i个人买了东西的概率。
分析:假设第i个人在有r个人买了东西的条件下买了东西的概率是\(P(A|B)\),r个人买了东西的概率是\(P(B)\),第i个人买了东西且r个人买了东西的概率是\(P(AB)\),则可得
\[P(A|B)=\frac{P(AB)}{P(B)} \]\(P(B)\)的计算方法:可以暴力求组合型枚举,枚举出是哪r个人买了东西,记录在q[i]
中,得出表达式:
其中下标i表示买了东西的,j对应没买的东西的。
\(P(AB)\)的计算方法:假设要计算的是第i个人买了东西且r个人买了东西的概率,可以先定下p[i]=1
,再组合型枚举剩下的r-1个人,套类似\(P(B)\)的公式即可。
综合在一起,可以通过一次组合型枚举,枚举所有r个人买东西的方案,顺便就可以计算\(P(AB)\)。
CODE
const int N=25;
int n,r;
int q[N];
double p[N];
double f[N],tot;//f表示每个人对应的P(AB),tot表示P(B)
void dfs(int k,int pos){
if(k>r){
double res=1;
for(int i=1;i<=n;i++){
if(!q[i])res*=(1-p[i]);
else res*=p[i];
}
tot+=res;
for(int i=1;i<=n;i++)if(q[i])f[i]+=res;
return;
}
for(int i=pos;i<=n;i++){
q[i]=1;
dfs(k+1,i+1);
q[i]=0;
}
}
int main(){
int T=1;
while(scanf("%d%d",&n,&r) && n){
for(int i=1;i<=n;i++)scanf("%lf",&p[i]);
memset(f,0,sizeof(f));
tot=0;
dfs(1,1);
printf("Case %d:\n",T++);
for(int i=1;i<=n;i++)printf("%.6lf\n",f[i]/tot);
}
}
全概率公式及其应用
可以通过对样本空间的划分,得出概率的一个递推关系式,有点类似dp中对状态集合的划分。这里对样本空间的划分必须保证不重不漏。
以下为全概率公式:
\[P(A)=\sum P(A\mid B_i)*P(B_i) \]紫书上的例子:假设考试考第\(k\)名的概率是\(P(B_k)\),考第\(k\)名被妈妈表扬的概率是\(P(A\mid B_k)\),因此被妈妈表扬的概率\(P(A)\)就可以用上述全概率公式求得。
应用:Double Patience - UVA 1637 - Virtual Judge (vjudge.net)
简单大意:有36张牌分成9堆,每堆4张牌,每次可以拿走牌堆顶部两张点数相同的牌,如果有多种拿法则等概率随机拿。如果最后拿完所有牌则游戏成功。给出牌堆,求成功的概率。
分析:可以用五进制数对牌堆每行有几张牌的状态进行压缩,例如初始状态(五进制数下):444444444,最多会有\(5^9=1953125\)种状态,假设在当前状态下获胜的概率是\(f(state)\),再根据每次拿牌的策略对样本空间进行划分,假设当前有tot种拿牌的方案,拿牌之后获胜的概率是\(f(t)\),根据全概率公式有:
\[f(state)=\sum f(t)*\frac{1}{tot} \](这不就是就是dp、记搜吗)
写一个记忆化搜索即可。
CODE:
const int N=1953125;
double f[N];
int st[N];
char s[10][5][3];
int pow5[11];
int cnt[11];
double dp(int state){
if(state==0)return 1;//成功
if(st[state])return f[state];//记搜
int tot=0;
for(int i=1;i<=9;i++){
if(!cnt[i])continue;
for(int j=i+1;j<=9;j++){
if(!cnt[j])continue;
if(s[i][cnt[i]][0]==s[j][cnt[j]][0]){
int t=state;
t=t-pow5[i-1]-pow5[j-1];
cnt[i]--; cnt[j]--;
f[state]+=dp(t);//全概率公式
cnt[i]++; cnt[j]++;
tot++;
}
}
}
st[state]=1;
if(!tot)return 0;//不能再操作说明失败了
else return f[state]/=tot;//否则计算概率
}
int main(){
pow5[0]=1;
for(int i=1;i<=9;i++){
pow5[i]=pow5[i-1]*5;//用来做"位"运算操作
cnt[i]=4;//表示每行有多少张牌
}
while(scanf("%s",s[1][1])!=EOF){//多组测试数据
memset(st,0,sizeof(st));
memset(f,0,sizeof(f));
for(int j=2;j<=4;j++)scanf("%s",s[1][j]);
for(int i=2;i<=9;i++){
for(int j=1;j<=4;j++){
scanf("%s",s[i][j]);
}
}
printf("%.6lf\n",dp(N-1));//从满牌开始递归
}
return 0;
}
标签:10,概率,紫书,个人,--,东西,int,state,AB 来源: https://www.cnblogs.com/tshaaa/p/16499870.html