Kids and Prizes SGU - 495

题意

\(n\)个奖品,装在\(n\)个盒子内,每个盒子有且仅有一个奖品。

\(m\)个人,每人依次选奖品,选择方式是从\(n\)个盒子内随机选择一个盒子。

如果盒子内有奖品,则取走,否则没有获得任何奖品。

盒子始终是\(n\)个,空盒子也一直存在。

求送出奖品数量的期望。

分析

\(dp[i][j]\)表示前\(i\)个人选了\(j\)个奖品的概率。

\(Ans = \sum_{j=0}^{n} dp[m][j] * j\)

考虑转移

\(dp[i][j] = dp[i - 1][j] * \frac jn + dp[i - 1][j - 1] *\frac{n - j + 1}{n}\)(分别是第\(i\)个人是否取到礼物的概率)

\(dp[0][0]=1\)

时间复杂度\(O(n^2)\)

考虑优化

考虑物

\(f_i\)表示前\(i\)个人选择结束后剩下的奖品个数。

\(f_i = f_{i-1} - \frac {f_{i-1}}{n}\) 前半部分是没拿到奖品,后半部分是拿到奖品。

\(f_i = (1 - \frac1n)f_{i-1} = (1 - \frac 1n)^i f_0 = n(1 - \frac 1n) ^i\)(因为\(f_0 = n\)),可以实数快速幂优化。

\(Ans = n - f_m\)

code

#include<bits/stdc++.h>
using namespace std;
#define ld long double 
ld ksm(ld x, int y){
	ld ret = 1; for(; y; y >>= 1, x = x * x) if(y & 1) ret = ret * x;
	return ret;
}
int n,m;

int main(){
    scanf("%d%d",&n,&m);
    printf("%.15Lf\n",(ld)n - (ld)n * ksm(1.0 - 1.0 / n, m));
	return 0;
}
posted @ 2020-08-08 16:33  zhuzihan  阅读(73)  评论(0编辑  收藏  举报