【Test 2016-10-2】chance {概率dp}

来源:互联网 发布:cherry键盘 mac 编辑:程序博客网 时间:2024/05/21 09:45
  • 【题目描述】
    pluto 去找妹子约会,然而要求和pluto 玩一个游戏,pluto 赢了才能获得约会的机会。游戏内容为:现在有N 个袋子(你可以认为它是哆啦A 梦的口袋,每个袋子里放着一些球),所以容量十分大,第i 个袋子里放着编号为Li 到Ri 的球(除编号外完全相同),pluto 需要从每个袋子里摸出一个球,第i 个袋子里任何一个球被摸到的概率是1/(Ri-Li + 1),如果pluto 摸出的球中有K% 或以上的球的编号的第一位是1(比如11,121,199 的第一位是1, 而21,233 第一位就不是1),那么pluto 就将赢得与约会的机会。现在pluto 想知道他能人生中第一次与妹子约会的概率有多大。

  • 【Sample Input】(第一行两个整数N,K;接下来N 行,每行两个整数,Li 和Ri)
    2 50
    1 2
    9 11

  • 【Sample Output】(一行一个实数(保留7 位小数)表示答案绝对误差不超过10^-6)
    0.8333333

  • 【数据范围】
    对于100% 的数据,0 <= k<=100,0 < Li<=Ri
    对于30% 的数据,n<=10,Li<=Ri<=100
    对于60% 的数据,n<=500,Li<=Ri<=2000
    对于100% 的数据,n<=2000,Li<=Ri<=10^18


  • 【题解】
    首先我们显然要先算出pluto从每个袋子里摸出第一位为1的球的概率{暴力随便做};
    设从第 i 个袋子里摸出满足要求的球的概率为p[i]:
    {状态} f [ i ] [ j ]:前i个袋子里取出 j 个第一位为1的球的概率
    {方程} f [ i ] [ j ] = f [ i ] [ j ] = f [ i - 1 ] [ j ] * ( 1 - p [ i ] ) + f [ i - 1 ] [ j - 1 ] * p [ i ] ; //分为i-1个已取j个和取j-1个考虑
    最后将取出球大于等于k%的状态累加即为答案。

#include <cstdio>#include <iostream>#define LL long longLL n,k,num[2005],l[2005],r[2005];double f[2005][2005],p[2005],ans;int main(){    scanf("%lld%lld\n",&n,&k);    for (int i=1;i<=n;++i) scanf("%lld%lld\n",&l[i],&r[i]);    for (int i=1;i<=n;++i)    {        LL t=1;        for (int j=0;j<=18 && t<=r[i];++j,t*=10)            if (l[i]<=t)            {                if (r[i]>=t+t-1) num[i]+=t;                else num[i]+=r[i]-t+1;            }            else if (l[i]<t+t) num[i]+=std::min(t+t,r[i]+1)-l[i];    }    for (int i=1;i<=n;++i) p[i]=1.0*num[i]/(r[i]-l[i]+1);    f[1][0]=1-p[1];f[1][1]=p[1];    for (int i=2;i<=n;++i)        for (int j=0;j<=i;++j)            f[i][j]=f[i-1][j]*(1-p[i])+f[i-1][j-1]*p[i];        int m=(n*k+99)/100;    for (int i=m;i<=n;++i) ans+=f[n][i];    printf("%.7f",ans);    return 0;}
0 0