题目链接: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
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.
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
桌子上有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
两种思路:
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
*/