uva 10288 coupons

来源:互联网 发布:美工作品图片幼儿园 编辑:程序博客网 时间:2024/05/21 08:46

Problem F

Coupons

Input: standard input

Output: standard output

Time Limit: 2 seconds

Memory Limit: 32 MB

 

Coupons in cereal boxes are numbered 1 to n, and a set of one of each is required for a prize (a cereal box, of course). With one coupon per box, how many boxes on average are required to make a complete set of n coupons?

Input

Input consists of a sequence of lines each containing a single positive integer n, 1<=n<=33, giving the size of the set of coupons. Input is terminated by end of file.

Output

For each input line, output the average number of boxes required to collect the complete set of n coupons. If the answer is an integer number, output the number. If the answer is not integer, then output the integer part of the answer followed by a space and then by the proper fraction in the format shown below. The fractional part should be irreducible. There should be no trailing spaces in any line of output.

Sample Input

2
5
17

Sample Output

3 
   5
11 --
   12
   340463
58 ------
   720720

题目大意:一共有n中不同的优惠券 ,每次得到每种优惠券的概率相同。问期望多少次可以得到所有n种优惠券。 a <= n <= 33

(吐槽一下原题目 ,英文的也很短 ,妈蛋看了半个小时没读懂,好歹也是过了六级的人,果然智商有限)


其实感觉这道题是下面这样的一道题的推广

抛一枚均匀的硬币直到出现k次正面为止,试求抛掷次数X的数学期望。

解:
令Xi表示出现i-1次正面后,到出现第i次正面的抛掷次数,则
X = X1 + X2 + ... + Xk

Xi服从几何分布,由期望公示E(X+Y) = E(X) + E(Y) 就可以得到结果

思维上的难度应当就是分解
将n次抛掷的过程仔细考察,由k次正面将n次抛掷分成k段 每一段的长度即为Xi
验证这样分解是正确大概是 这n抛掷k次正面 符合这种情况的单个样本发生的概率 为 p^k * (1 - p) ^ (n - k) 
对于X=n 中的任何一个样本 Xi的和需要每个Xi同时成立满足 概率为Xi单个的乘积 也为  p^k * (1 - p) ^ (n - k) 
然后考察 样本总数
每一个n抛掷k次正面的样本点 都可由Xi的唯一一个样本点表示,反过来也是这样
所以应当是一一对应 所以 X 与 Xi 的和 的分布律是相同的
(以上分析很有可能是不对的, 欢迎修正)

将这两个题目联系起来
令Xi 表示出现i 种不同的优惠券后, 到出现第i次不同的优惠券的次数
就和上一道题目一样了

算法分析:假设当前已经有k种优惠券,那么获得新优惠券的概率是(n-k).n,所以需要部署的期望是n/(n-k).。求和得到不熟的期望是n/n + n/(n-1) +... +n/1 = n * sigma(1/i)

AC代码
#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <cstdlib>#include <cassert>using namespace std;typedef long long LL;LL n, r;LL p, q;LL gcd(LL a, LL b){if(b == 0){return a;}return gcd(b, a % b);}void reduction(LL &a, LL &b){LL d = gcd(a, b);a /= d;b /= d;}void addF(int a, int b){p = p * b + a * q;//cout << p << " " ;q *= b;reduction(p, q);}void printF(LL p){LL rr = r;while(rr){printf(" ");rr /= 10;}printf(" ");printf("%lld\n", p);}int main(){#ifdef DEBUGFILE *fPtr = freopen("a.in", "r", stdin);assert(fPtr != NULL);fPtr = freopen("a.out", "w", stdout);assert(fPtr != NULL);#endifwhile(scanf("%lld", &n) == 1){p = 0LL, q = 1LL;r = n;for(LL i = 1; i <= n; i++){addF(1, i);}//cout << p << "  " << q << endl;reduction(r, q);p *= r;//cout << "p = " << r << endl;r = p / q;p %= q;if(p % q == 0){printf("%lld\n", r);}else{printF(p);printf("%lld ", r);LL qq = q;while(qq){printf("-");qq /= 10;}printf("\n");printF(q);}}return 0;}



(不得不说uva一直很受伤人 有时候多一个空格都是wa  而不是pe
代码很丑 很简单的代码改了n遍才能正确表达意思 也是很久没写代码的缘故了 伤心)

题目大意 算法分析 来自《题目与解读》

原创粉丝点击