zoukankan      html  css  js  c++  java
  • Card Collector

    Card Collector

    有n种卡,每一卡包有概率(p_i)出现卡i,只会出现一张以下的卡,询问卡包的期望数包含所有种类的卡,(1 <= N <= 20)

    法一:容斥原理

    注意到数据范围很小,再此我们能很轻松地求出一种卡摸到的期望,而此时摸到的期望包含了其他的部分,于是考虑容斥。

    不难有一种卡i,其摸到的期望数为(frac{1}{p_i}),而对于摸到卡i,或者j的期望数不难得知,即把它们看成一个整体(frac{1}{p_i+p_j}),于是我们可以以此为容斥依据,进行容斥即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    using namespace std;
    double w[20];
    int main(){
        double sxr,ans;
        int n,i,j,li,tot;
        while(scanf("%d",&n)!=EOF){
            for(i=0;i<n;++i)scanf("%lf",&w[i]);
            li=1<<n,ans=0;
            for(i=1;i<li;++i){
                tot&=0,sxr=0;
                for(j=0;j<n;++j)
                    if(i>>j&1)sxr+=w[j],++tot;
                if(tot&1)ans+=1/sxr;
                else ans-=1/sxr;
            }printf("%.5lf
    ",ans);
        }
        return 0;
    }
    

    法二:无后效性处理

    注意到为期望题,而样本空间无限大,考虑无后效性做法,即以期望代无限状态,设(E(x))表示已经摸到x对应二进制的卡种数的期望卡包数(如(E(3))表示已经摸到第1中卡和第二种卡的卡包数期望),于是不难有转移

    [E(x)=1+sum E(x)p_i+sum E(y)p_j ]

    其中(E(x)p_i)表示摸到已经摸过的卡,概率分别为(p_i),y则是对应二进制位已经把没摸过的卡记录下来,概率分别为(p_j)

    例如,只有2种卡,设(p_0)为没有摸到任何卡的概率

    [E(0)=1+E(0)p_0+E(1)p_1+E(2)p_2 ]

    [E(1)=1+E(1)(p_0+p_1)+E(3)p_2 ]

    [E(2)=1+E(2)(p_0+p_2)+E(3)p_1 ]

    [E(3)=0 ]

    于是对一般式变换一下,我们有

    [E(x)=frac{1+sum E(y)p_j}{(1-sum p_i)} ]

    以此为递推依据记忆化搜索即可。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    using namespace std;
    int n;double w[21];
    double dp[1048576];
    il double search(int);
    int main(){
        int i,li;
        while(scanf("%d",&n)!=EOF){
            w[n]=1;for(i=0;i<n;++i)scanf("%lf",&w[i]),w[n]-=w[i];
            memset(dp,-127,sizeof(dp)),li=(1<<n)-1,dp[li]=0;
            printf("%.5lf
    ",search(0));
        }return 0;
    }
    il double search(int er){
        if(dp[er]>=0)return dp[er];
        int i;double mom(1-w[n]),son(1);
        for(i=0;i<n;++i)
            if(er>>i&1)mom-=w[i];
            else son+=search(er|1<<i)*w[i];
        return dp[er]=son/mom;
    }
    
    
  • 相关阅读:
    【转】卡特兰数四个公式(简单)
    【基础算法-ST表】入门 -C++
    【题解】[Nwerc 2006]escape -C++
    C#高级编程第11版
    C#高级编程第11版
    C#高级编程第11版
    C#高级编程第11版
    C#高级编程第11版
    109th LeetCode Weekly Contest Knight Dialer
    109th LeetCode Weekly Contest Number of Recent Calls
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10839273.html
Copyright © 2011-2022 走看看