概率 && 期望 入门

来源:互联网 发布:qq伪装手机型号软件 编辑:程序博客网 时间:2024/06/14 19:47

uva11021
题意:
给你K个毛球,每个毛球只能生存一天,但是每个毛球都有pi的概率繁殖i个毛球,问第 m 天后所有毛球死亡的概率。(所有毛球独立存在,互不影响)

思路:

概率dp

因为k只毛球都是相互独立的,我们只需要算出每个毛球m天死亡后的概率dp[m],然后答案就是 dp[m]k
设dp[i]表示所有毛球第i天后全部死亡的概率.
那么有
dp[i]=p0+p1dp[i1]1+p2dp[i1]2....pjdp[i1]j
其中pj表示繁殖j个毛球的概率.
每只毛球到要在i-1天死亡,一共有几个毛球,所以为dp[i1]j

#include<iostream>#include<cmath>#include<cstdio>using namespace std;const int maxn = 1e3+5;double p[maxn],dp[maxn];int n,m,k;int main(){    int _,ca = 1;    cin>>_;    while(_--)    {        scanf("%d %d %d",&n,&k,&m);        for(int i = 0;i < n;++i)         scanf("%lf",&p[i]);        for(int i = 1;i <= m;++i)        {            dp[i] = 0;            for(int j = 0;j < n;++j)            dp[i] += p[j]*pow(dp[i-1],j);        }        double ans = pow(dp[m],k);        if(m == 0) ans = 0.0;        printf("Case #%d:  %.7f\n",ca++,ans);    }    return 0;} 

uva11722

题意:
你和朋友都要乘坐火车,并且都会途径A城市。你们很想会面,但是你们到达这个城市的准确时刻都无法确定。你会在时间区间[t1,t2]中的任意时刻以相同的概率密度到达。你的朋友则会在时间区间[s1,s2]的任意时刻以相同的概率密度到达。你们的火车都会在A城市停留w分钟。只有你们所在的火车都停在A城市的时候,才可能会面。你的任务是计算出现这种情况的概率。

思路:

几何概型.
我已经忘了我高中学的所有知识….
一般可能性无穷的,或者一段区间,一个区域啊让你求概率啊 都可以想想几何概型.

如图

设x轴为 t,y轴为s.则 (t1,t2)和(s1,s2)围出的矩阵为整个可能的全集。
因为两人要相遇即差为w,所以在画两条直线 s = t - w 和s = t + w.那么所有可行解即为两条直线之间和矩阵共同围成的面积.
阴影部分面积/矩阵面积 即为概率。

两个直线和矩阵有很多画法,计算时需要分类讨论

#include<bits/stdc++.h>using namespace std;int t1,t2,s1,s2,w;int ww,hh;double solve(int w){    int ly,ry,ux,dx;    ly = t1 + w;    ry = t2 + w;    if(ly >= s2 )    return 0.0;    if(ry <= s1)     return ww*hh;    ux = s2 - w;    dx = s1 - w;    if(ly >= s1 && ly <= s2 && ux >= t1 && ux <= t2) return (ux - t1)*(s2 - ly)*0.5;    if(ry >= s1 && ry <= s2 && dx >= t1 && dx <= t2) return (ww*hh - (t2 - dx)*(ry - s1)*0.5);    if(dx >= t1 && dx <= t2 && ux >= t1 && ux <= t2) return (s2 - s1)*(ux - t1 + dx - t1)*0.5;    if(ly >= s1 && ly <= s2 && ry >= s1 && ry <= s2) return (t2 - t1)*(s2 - ly + s2 - ry)*0.5;}int main(){    int _,ca = 1;    cin>>_;    while(_--)    {        scanf("%d %d %d %d %d",&t1,&t2,&s1,&s2,&w);         ww = t2 - t1;         hh = s2 - s1;        double ans1 = solve(w);        double ans2 = solve(-w);        //printf("%f %f",ans1,ans2);        printf("Case #%d:  %.8f\n",ca++,(ans2-ans1)/(ww*hh));    }    return 0;}

uva 11762

题意:
给你一个整数N,每次都可以在不超过N的素数中随机选择一个P,如果P是N的约数,则把N变成N/P,否则N不变,问平均情况下要多少次随机选择,才能把N变成1

思路:
期望dp.
考虑dp[n]表示整数N变为1需要的期望次数.
那么有:
dp[i]=1+dp[i](1g(i)p(i))+k|idp[i/k]1g(i)
其中g(i)为不超过i的素数中约数的个数
p(i)为不超过i的素数的个数.
整理一下得:
dp[i]=k|idp[i/k]+p(i)g(i)

由于i/ k < i 所以这个过程可以记忆化搜索一下.

#include<bits/stdc++.h>using namespace std;const int maxn = 1e6+5;typedef long long ll;int n;double dp[maxn];int prime[maxn],cnt;bool vis[maxn];void init(){    cnt = 0;    for(int i = 2;i < maxn;++i)    {        if(!vis[i])            prime[cnt++] = i;        for(int j = 0;j < cnt && (ll)prime[j]*i < maxn;++j)        {            vis[i*prime[j]] = 1;            if(i % prime[j] == 0) break;        }    }    return ;}double dfs(int x){    if(dp[x] != -1) return dp[x];    double ans = 0;    int g = 0,p = 0;    for(int i = 0;i < cnt && prime[i] <= x;++i)    {        p++;        if(x % prime[i] == 0)        {            g++;            ans += dfs(x / prime[i]);        }    }    ans = (ans + p)*1.0 / g;    return dp[x] = ans;}int main(){    int _,ca = 1;    for(int i = 0;i < maxn;++i) dp[i] = -1.0;    dp[1] = 0;    init();    cin>>_;    while(_--)    {        scanf("%d",&n);        dfs(n);        printf("Case %d: %.10f\n",ca++,dp[n]);    }    return 0;}
原创粉丝点击