UVA 10288 - Coupons(数学期望+分数计算)

题目链接 https://cn.vjudge.net/problem/UVA-10288

【题意】
有n种不同的彩票,如果搜集齐所有的彩票就可以兑换大奖(n<=33)而每次买到的彩票种类是随机的,问你在平均情况下,需要买多少张彩票才能兑换大奖呢?用分数表示答案

【思路】
已经有 k 种彩票,设 s=kn ,那么假设再买到一种新的彩票需要的次数为 t 次,对应的概率为 st1(1s),所以平均需要的次数为

C(k)=t=1+st1(1s)t=(1s)t=1+st1t
然后用错位相减法,设
F(t)=t=1+st1t=1+2s+3s2+4s3+......
sF(t)=t=1+stt=s+2s2+3s3+4s4+......
F(t)sF(t)=1+s+s2+s3+...=limn+1sn+11s=11s
所以
F(t)=1(1s)2
C(k)=11s=nnk
最后的结果即为
k=0n1C(k)=nk=0n11nk

结果需要用分数表示,这里存一个分数计算的板子

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

long long __gcd(long long a,long long b){
    if(b==0) return a;
    return __gcd(b,a%b);
}

struct fraction {
    long long numerator;//分子
    long long denominator;//分母
    fraction() {
        numerator = 0;
        denominator = 1;
    }
    fraction(long long num) {
        numerator = num;
        denominator = 1;
    }
    fraction(long long a, long long b) {
        numerator = a;
        denominator = b;
        this->reduction();
    }

    void operator = (const long long num) {
        numerator = num;
        denominator = 1;
        this->reduction();
    }

    void operator = (const fraction &b) {
        numerator = b.numerator;
        denominator = b.denominator;
        this->reduction();
    }

    fraction operator + (const fraction &b) const {
        long long gcdnum = __gcd(denominator, b.denominator);
        fraction tmp = fraction(numerator*(b.denominator/gcdnum) + b.numerator*(denominator/gcdnum), denominator/gcdnum*b.denominator);
        tmp.reduction();
        return tmp;
    }

    fraction operator + (const int &b) const {
        return ((*this) + fraction(b));
    }

    fraction operator - (const fraction &b) const {
        return ((*this) + fraction(-b.numerator, b.denominator));
    }

    fraction operator - (const int &b) const {
        return ((*this) - fraction(b));
    }

    fraction operator * (const fraction &b) const {
        fraction tmp = fraction(numerator*b.numerator, denominator * b.denominator);
        tmp.reduction();
        return tmp;
    }

    fraction operator * (const int &b) const {
        return ((*this) * fraction(b));
    }

    fraction operator / (const fraction &b) const {
        return ((*this) * fraction(b.denominator, b.numerator));
    }

    void reduction() {
        if (numerator == 0) {
            denominator = 1;
            return;
        }
        long long gcdnum = __gcd(numerator, denominator);
        numerator /= gcdnum;
        denominator /= gcdnum;
    }
};

fraction a[50];

int main(){
    int n;
    while(scanf("%d",&n)==1){
        for(int i=1;i<=n;++i){
            a[i]=fraction(1,i);
        }
        for(int i=2;i<=n;++i){
            a[1]=a[1]+a[i];
        }
        a[1]=a[1]*n;
        long long x=a[1].numerator;
        long long y=a[1].denominator;
        if(y==1) printf("%lld\n",x);
        else{
            long long tmp=x/y,tmpy=y;
            int ctmp=0,cy=0;
            while(tmp){
                ++ctmp;
                tmp/=10;
            }
            while(tmpy){
                ++cy;
                tmpy/=10;
            }
            for(int i=0;i<=ctmp;++i) putchar(' ');
            printf("%lld\n",x%y);
            printf("%lld ",x/y);
            for(int i=0;i<cy;++i) putchar('-');
            puts("");
            for(int i=0;i<=ctmp;++i) putchar(' ');
            printf("%lld\n",y);
        }
    }
    return 0;
}
posted @ 2018-08-24 11:28  不想吃WA的咸鱼  阅读(187)  评论(0编辑  收藏  举报