题目链接 https://cn.vjudge.net/problem/UVA-10288
【题意】
有n种不同的彩票,如果搜集齐所有的彩票就可以兑换大奖(n<=33)而每次买到的彩票种类是随机的,问你在平均情况下,需要买多少张彩票才能兑换大奖呢?用分数表示答案
【思路】
已经有 kk 种彩票,设 s=kns=kn ,那么假设再买到一种新的彩票需要的次数为 tt 次,对应的概率为 st−1(1−s)st−1(1−s),所以平均需要的次数为
C(k)=∑t=1+∞st−1(1−s)t=(1−s)∑t=1+∞st−1tC(k)=∑t=1+∞st−1(1−s)t=(1−s)∑t=1+∞st−1t
然后用错位相减法,设
F(t)=∑t=1+∞st−1t=1+2s+3s2+4s3+......F(t)=∑t=1+∞st−1t=1+2s+3s2+4s3+......
sF(t)=∑t=1+∞stt=s+2s2+3s3+4s4+......sF(t)=∑t=1+∞stt=s+2s2+3s3+4s4+......
则
F(t)−sF(t)=1+s+s2+s3+...=limn→+∞1−sn+11−s=11−sF(t)−sF(t)=1+s+s2+s3+...=limn→+∞1−sn+11−s=11−s
所以
F(t)=1(1−s)2F(t)=1(1−s)2
C(k)=11−s=nn−kC(k)=11−s=nn−k
最后的结果即为
∑k=0n−1C(k)=n∑k=0n−11n−k∑k=0n−1C(k)=n∑k=0n−11n−k
结果需要用分数表示,这里存一个分数计算的板子
#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;
}