题目链接:http://codeforces.com/problemset/problem/768/D
题意:给你概率 p/2000 ,k种东西,每种东西取到的概率相同。q次询问问取多少次能使得每种东西至少一个的概率能达到给定值。k,q,p小于1000。
题解:概率用dp递推,dp[i]代表已有 i 种东西的概率,滚动此数组来模拟取的次数,记录dp[k]为每次的答案方便询问查询。
由于p范围概率最大为0.5,在k取最大值1000时也只用大约7000多次循环即可达到这个概率。
dp方程:dp[i] = dp[i] * i / k + dp[i - 1] * (k - i + 1) / k
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <functional>
#include <map>
#include <bitset>
#define INF 0x7fffffff
#define REP(i,j,k) for(int i = j;i <= k;i++)
#define squr(x) (x) * (x)
#define lowbit(x) (x&(-x))
#define getint(x) scanf("%d", &(x))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e3 + 10;
const double eps = 1e-7;
int k, q;
int p;
double dp[MAXN];
double ans[100010];
int main(int argc, const char * argv[]) {
getint(k);
getint(q);
dp[1] = 1;
if (k == 1) {
ans[1] = 1;
}
REP(i, 1, 10000) {
for (int j = k; j > 0; j--) {
dp[j] = dp[j] * (double)j / k + dp[j - 1] * (double)(k - j + 1) / k;
}
ans[i + 1] = dp[k];
//cout << pp[k] << endl;
if (dp[k] > 0.6) {
break;
}
}
REP(i, 1, q) {
getint(p);
double tt = p / 2000.0;
for (int i = 1; i <= 10000; i++) {
if (ans[i] - tt >= 0) {
printf("%d\n", i);
break;
}
}
}
return 0;
}