概率 && 期望 入门

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
#include
#include
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城市的时候,才可能会面。你的任务是计算出现这种情况的概率。

思路:

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

概率 && 期望 入门_第1张图片

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

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

#include

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

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;
}

你可能感兴趣的:(数学期望,dp)