HDU 5159 Card(DP+组合数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5159



Problem Description
There are x cards on the desk, they are numbered from 1 to x. The score of the card which is numbered i(1<=i<=x) is i. Every round BieBie picks one card out of the x cards,then puts it back. He does the same operation for b rounds. Assume that the score of the j-th card he picks is  Sj . You are expected to calculate the expectation of the sum of the different score he picks.
 

Input
Multi test cases,the first line of the input is a number T which indicates the number of test cases. 
In the next T lines, every line contain x,b separated by exactly one space.

[Technique specification]
All numbers are integers.
1<=T<=500000
1<=x<=100000
1<=b<=5
 

Output
Each case occupies one line. The output format is Case #id: ans, here id is the data number which starts from 1,ans is the expectation, accurate to 3 decimal places.
See the sample for more details.
 

Sample Input
 
 
2 2 3 3 3
 

Sample Output
 
 
Case #1: 2.625 Case #2: 4.222
Hint
For the first case, all possible combinations BieBie can pick are (1, 1, 1),(1,1,2),(1,2,1),(1,2,2),(2,1,1),(2,1,2),(2,2,1),(2,2,2) For (1,1,1),there is only one kind number i.e. 1, so the sum of different score is 1. However, for (1,2,1), there are two kind numbers i.e. 1 and 2, so the sum of different score is 1+2=3. So the sums of different score to corresponding combination are 1,3,3,3,3,3,3,2 So the expectation is (1+3+3+3+3+3+3+2)/8=2.625
 

Source


题意(转):

问题描述
桌子上有a张牌,每张牌从1到a编号,编号为i(1<=i<=a)的牌上面标记着分数i , 每次从这a张牌中随机抽出一张牌,然后放回,执行b次操作,记第j次取出的牌上面分数是 Sj , 问b次操作后不同种类分数之和的期望是多少。
输入描述
多组数据,第一输入数据组数T ,接下来T行,每行两个整数a,b以空格分开


[参数说明]
所有输入均为整数
1<=T<=500000
1<=a<=100000
1<=b<=5
输出描述
输出答案占一行,输出格式为 Case #x: ans, x是数据编号从1开始,ans是答案,精确到小数点后3位。
看样例可以得到更多信息。
输入样例
2
2 3
3 3
输出样例
Case #1: 2.625
Case #2: 4.222

提示:
对于第一组数据所有牌型的组合为(1, 1, 1),(1,1,2),(1,2,1),(1,2,2),(2,1,1),(2,1,2),(2,2,1),(2,2,2)
对于(1,1,1)这个组合,他只有一种数字,所以不同数字之和为1
而对于(1,2,1)有两种不同的数字,即1和2,所以不同数字之和是3。
所以对应组合的不同数字之和为1,3,3,3,3,3,3,2
所以期望为(1+3+3+3+3+3+3+2)/8=2.625

PS:

两种思路:

1:

设Xi代表分数为i的牌在b次操作中是否被选到,Xi=1为选到,Xi=0为未选到
那么期望EX=1*X1+2*X2+3*X3+…+x*Xx
Xi在b次中被选到的概率是1-(1-1/x)^b
那么E(Xi)= 1-(1-1/x)^b
那么EX=1*E(X1)+2*E(X2)+3*E(X3)+…+x*E(Xx)=(1+x)*x/2*(1-(1-1/x)^b)
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
int main()
{
    int t;
    int x, b;
    int cas = 0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&x,&b);
        double p = 1-pow(1-1.0/x,b);
        double n = x*(x+1.0)/2;
        double ans = n*p;
        printf("Case #%d: %.3lf\n",++cas,ans);
    }
}

2:
dp思想,先预处理出dp[i][j]: i 个数 j 轮!
因为每个数字出现的总次数是相同的!
我们只要找出数字出现的总的有效次数!再乘上所有数的和,就可以求出所有数字的有效和,最后再除以总的组合数即可!
其实写两个案例我们就可以发现,每个数字的有效次数是相邻的i的j次方差!
因为每次都有(i-1)^j次方的组合里可以不含i个数字其中的一个!
例如:x = 3, b = 3时
我们有组合
(1,1,1)、(1,1,2)、(1,2,1)、(1,2,2)
(2,2,2)、(2,1,1)、(2,1,2)、(2,2,1)
这8个组合里不含数字 3
同理还有 8 个组合不含数字 1, 8 个不含数字 2 !
那么1,2,3出现的有效次数就是总的组合 num = x^b - (x-1)^b!
sn = x*(x+1)/2;
sum = sn*num;
代码如下:
#include <cstdio>
#include <cstring>
#define maxn 100010
double dp[maxn][6];
//dp[i][j]: i 个数 j 轮
void init()
{
    for(int i = 1; i <= 5; i++)
    {
        dp[1][i] = 1;
    }
    for(int i = 2; i <= 100000; i++)
    {
        dp[i][1] = dp[i-1][1]+i;
        double cnt1, cnt2;
        for(int j = 2; j <= 5; j++)
        {
            cnt1 = cnt2 = 1;
            for(int k = 1; k <= j; k++)
            {
                cnt1 *= i;
                cnt2 *= i-1;
            }
            double cishu = (double)cnt1-cnt2;//次方差
            double sum = (double)i*(1+i)/2.0;
            dp[i][j] = cishu*sum;
        }
    }
}
int main()
{
    int x, b;
    int t;
    int cas = 0;
    init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&x,&b);
        double tol = 1;
        for(int i = 1; i <= b; i++)//x^b
        {
            tol*=x;
        }
        double ans = dp[x][b]/tol;
        printf("Case #%d: %.3f\n",++cas,ans);
    }
    return 0;
}
/*
99
2 3
3 3
1 3
3 1
3 2
100000 5
*/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值