您的位置:首页 > 其它

SGU 495 Kids and Prizes 概率DP 或 数学推理

2015-02-15 10:45 465 查看
题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=495

有n个箱子 m个人

有两个思考的角度

1.从箱子的角度

对于一个箱子来说 不被选中的概率是((n-1)/n)^m 所以被选中的概率是(1 - ((n-1)/n)^m)

箱子之间是互相独立的

所以总期望是:n * (1 - ((n-1)/n)^m)

【我是算样例然后无意中发现的规律 再证明】

2.从人的角度

从题目中看 人是one by one进去选的 所以可以看作有先后顺序 考虑动态规划

dp[i]表示第i个人选到礼物的概率

两种情况:

a.若第i-1个人没有选到 那么第i个人获得礼物的概率跟第i-1个人一样 因为礼物数没有减少 则有(1 - dp[i-1]) * dp[i-1]

b.若第i-1个人有选到 那么礼物数减少了1 所以获得礼物的概率就减少了1/n 则有dp[i-1] * (dp[i-1] - 1/n)

综上 有dp[i] = (1 - dp[i-1]) * dp[i-1] + dp[i-1] * (dp[i-1] - 1/n);

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>
#include <vector>

using namespace std;

int main()
{
//freopen("in.txt", "r", stdin);

double n, m;

scanf("%lf%lf", &n, &m);

printf("%.9f\n", n * (1 - pow((n-1)/n, m) ));

return 0;
}


#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <set>
#include <queue>
#include <vector>

using namespace std;

const int maxn = 100010;
double dp[maxn];

int main()
{
//freopen("in.txt", "r", stdin);

int n, m;

scanf("%d%d", &n, &m);

dp[1] = 1;

for(int i = 2; i <= m; i++)
{
dp[i] = dp[i-1]*(dp[i-1] - 1.0/n) + (1 - dp[i-1])*dp[i-1];
}

double ans = 0;
for(int i = 1; i <= m; i++)
ans += dp[i];

printf("%.9f\n", ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: