UVa 10288
题意:给你n个Conous,每个出现的概率相等,问你每次随机生成一个Conous,需要的次数的期望。
思路:令dp[i]代表还需要产出i个不同的未出现的Conous的期望次数,即前面的序列已经产出了n-i个
那么有dp[i]=(i/n)(1+dp[i-1])+(1-i/n)(1+dp[i])
i/n*dp[i]=1+i/n*dp[i-1]
dp[i]=n/i+dp[i-1]
dp[n]=sum(n/i) | i=1 to n
注意分数的运算就可以了
// author:latstars
// time:20161122 19:00
// 概率
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int maxn=100;
typedef long long LL;
struct Fraction{
LL numerator;
LL denominator;
LL integer;
Fraction(){}
Fraction(LL n,LL m,LL i)
{
integer=i;
if(n>=m){
integer=i+n/m;
n-=n/m*m;
}
LL g=__gcd(m,n);
m/=g;
n/=g;
numerator=n;
denominator=m;
}
};
Fraction operator + (const Fraction & A,const Fraction & B)
{
LL a,b,c;
a=A.integer+B.integer;
b=c=0;
c=A.denominator*B.denominator;
b=A.numerator*B.denominator+B.numerator*A.denominator;
if(b>=c){
a+=b/c;
b-=b/c*c;
}
LL g=__gcd(c,b);
b/=g;c/=g;
return Fraction(b,c,a);
}
int n;
void solve(void)
{
Fraction ans(0,1,0);
for(int i=1;i<=n;i++){
Fraction f(1LL*n,1LL*i,0LL);
ans=ans+f;
}
if(ans.numerator){
int len1=0,len2=0,len3=0;
LL a=ans.numerator,b=ans.denominator,c=ans.integer;
while(a){
len1++;
a/=10;
}
while(b){
len2++;
b/=10;
}
while(c){
len3++;
c/=10;
}
int h=max(len1,len2),sp=len3+1;
for(int i=1;i<=sp;i++)
printf(" ");
printf("%lld\n",ans.numerator);
printf("%lld ",ans.integer);
for(int i=1;i<=h;i++)
printf("-");
puts("");
for(int i=1;i<=sp;i++)
printf(" ");
printf("%lld\n",ans.denominator);
}
else{
printf("%lld\n",ans.integer);
}
}
int main()
{
while(scanf("%d",&n)!=EOF){
solve();
}
return 0;
}