hdu 4336 Card Collector

来源:互联网 发布:淘宝店铺怎么优化标题 编辑:程序博客网 时间:2024/05/02 01:52
Description
In your childhood, do you crazy for collecting the beautiful cards in the snacks? They said that, for example, if you collect all the 108 people in the famous novel Water Margin, you will win an amazing award.

As a smart boy, you notice that to win the award, you must buy much more snacks than it seems to be. To convince your friends not to waste money any more, you should find the expected number of snacks one should buy to collect a full suit of cards.

Input
The first line of each test case contains one integer N (1 <= N <= 20), indicating the number of different cards you need the collect. The second line contains N numbers p1, p2, ..., pN, (p1 + p2 + ... + pN <= 1), indicating the possibility of each card to appear in a bag of snacks.

Note there is at most one card in a bag of snacks. And it is possible that there is nothing in the bag.

Output
Output one number for each test case, indicating the expected number of bags to buy to collect all the N different cards.

You will get accepted if the difference between your answer and the standard answer is no more that 10^-4.

Sample Input
1
0.1
2
0.1 0.4

Sample Output
10.000
10.500

题目大意:就是要你收集n张卡片,每次收集到第i张卡片的概率为p[i],求出要收集到所有卡片需要卖多少袋零食;

解题思路:看了别人的代码发现本题主要是利用容斥原理,如果这个懂了,代码就很简单,

容斥原理:

其中1/pi就类似于高中数学的几何分布的期望,这样看式子就很明了了。

#include<stdio.h>double p[22];int main(){int n,i,j,a;double temp,s;while(scanf("%d",&n)!=EOF){for(i=0;i<n;i++)scanf("%lf",&p[i]);s=0;for(i=1;i<(1<<n);i++){a=0;temp=0;for(j=0;j<n;j++){if(i&(1<<j)){temp+=p[j];a++;}}if(a&1)(奇加偶减)s+=1.0/temp;else s-=1.0/temp;}printf("%.4lf\n",s);//我开始用的是%.3lf结果wa,后来看别人的是%.4lf一提交就ac了,我也不太明白你可以问一下别的大牛}return 0;}

还有一种做法是dp,但我不会;直接copy了别人的。请原谅我额,我想以后再看

#include <cstdlib>#include <cstring>#include <cstdio>using namespace std;int N;double seq[25], dp[1100000], p[1100000];void pre(){    int LIM = 1 << N;    for (int i = 0; i < LIM; ++i) {        p[i] = 0;        for (int j = 0; j < N; ++j) {            if ((1 << j) & i) {                   p[i] += seq[j];            }            }    }}int main(){    int temp;    double n, tot, myself;    while (scanf("%d", &N) == 1) {        dp[(1<<N)-1] = none = 0;        for (int i = 0; i < N; i++) {            scanf("%lf", &seq[i]);            n+= seq[i];        }        n= 1 - none;        pre();        for (int i = (1<<N)-2; i >= 0; --i) {            tot = 0;            myself = p[i] + n;             for (int j = 0; j < N; ++j) {                if (!((1 << j)&i)) {                     temp = i | (1 << j);                    tot += seq[j] * dp[temp];                }            }            dp[i] = (tot + 1) / (1 - myself);        }        printf("%.4lf\n", dp[0]);    }    return 0;}


原创粉丝点击