UVA - 11427
Time Limit: 2000MS | Memory Limit: Unknown | 64bit IO Format: %lld & %llu |
Description
Problem A
Expect the Expected
Input: Standard Input
Output: Standard Output
Some mathematical background. This problem asks you to compute the expected value of a random variable. If you haven't seen those before, the simple definitions are as follows. A random variable is a variable that can have one of several values, each with a certain probability. The probabilities of each possible value are positive and add up to one. The expected value of a random variable is simply the sum of all its possible values, each multiplied by the corresponding probability. (There are some more complicated, more general definitions, but you won't need them now.) For example, the value of a fair, 6-sided die is a random variable that has 6 possible values (from 1 to 6), each with a probability of 1/6 . Its expected value is 1/6 + 2/6 + ... + 6/6 = 3.5 . Now the problem.
I like to play solitaire. Each time I play a game, I have probability p of solving it and probability (1- p) of failing. The game keeps statistics of all my games - what percentage of games I have won. If I simply keep playing for a long time, this percentage will always hover somewhere around p*100% . But I want more.
Here is my plan. Every day, I will play a game of solitaire. If I win, I'll go to sleep happy until the next day. If I lose, I'll keep playing until the fraction of games I have won today becomes larger than p. At this point, I'll declare victory and go to sleep. As you can see, at the end of each day, I'm guaranteed to always keep my statistics above the expected p*100% . I will have beaten mathematics!
If your intuition is telling you that something here must break, then you are right. I can't keep doing this forever because there is a limit on the number of games I can play in one day. Let's say that I can play at most n games in one day. How many days can I expect to be able to continue with my clever plan before it fails? Note that the answer is always at least 1 because it takes me a whole day of playing to reach a failure.
Input
The first line of input gives the number of cases, N. N test cases follow. Each one is a line containing p (as a fraction) and n.
1 ≤ N ≤ 3000, 0 ≤ p < 1,
The denominator of p will be at most 1000,
1 ≤ n ≤ 100.
Output
For each test case, print a line of the form "Case #x: y", where y is the expected number of days, rounded down to the nearest integer. The answer will always be at most 1000 and will never be within 0.001 of a round-off error case.
Sample Input Output for Sample Input
4 1/2 1 1/2 2 0/1 10 1/2 3 | Case #1: 2 Case #2: 2 Case #3: 1 Case #4: 2 |
Problemsetter: Igor Naverniouk
Special thanks: Frank Chu
Source
Root :: Prominent Problemsetters :: Igor Naverniouk (Abednego)
题意:
每天晚上都玩纸牌游戏,每一盘游戏赢的概率为p,如果该晚上的胜率超过p就高高兴兴的去睡觉了,否则一直继续玩,如果该天晚上完了n次胜率都还没超过p,就垂头丧气的去睡觉,并且以后再也不玩了。
问平均情况下,你会玩多少晚上游戏。
因为各晚上之间是相互独立的,可以考虑先求出一晚上垂头丧气去睡觉的概率Q。
Q=sum( P(玩了n次赢了i次) ) i/n <= p; 可以通过dp求出
dp[i][j] 表示玩了i次赢了j次的概率并且满足j/i <= p。
然后求出Q后,再计算天数的期望
一天的概率 : Q
两天的概率 :(1-Q) * Q
三天的概率: (1-Q) ^ 2 * Q
....
E = Q + 2*Q*(1-Q) + 3*Q*(1-Q)^2 ...
令 s = E / Q = 1 + 2*(1-Q) + 3*(1-Q)^2 ... (1)
则 (1-Q)s = (1-Q) + 2(1-Q)^2 + ... (2)
(1) - (2) 的 E = Qs = 1+(1-Q) + (1-Q)^2 + (1-Q)^3 + ... = 1 / Q
另外一种方法也可得E = 1 / Q :
设数学期望为e天,吧情况分为两类:
第一天晚上垂头丧气的概率为Q,玩游戏天数为1
第一天晚上高高兴兴的概率为(1-Q),玩游戏天数为e+1
则:
e = Q * 1 + (1-Q) * (e+1)
解的e = 1/Q
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100 + 20;
double dp[maxn][maxn];
int main() {
int T;
scanf("%d", &T);
for(int kase=1; kase<=T; kase++) {
int a, b, n;
scanf("%d/%d%d", &a, &b, &n);
double p = (double) a / b;
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(int i=1; i<=n; i++) {
for(int j=0; j*b<=i*a; j++) {
dp[i][j] = dp[i-1][j] * (1-p);
if(j) dp[i][j] += dp[i-1][j-1] * p;
}
}
double Q = 0;
for(int i=0; i*b<=n*a; i++) Q += dp[n][i];
int ans = (int) (1 / Q);
printf("Case #%d: %d\n", kase, ans);
}
return 0;
}