题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1229
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <utility>
using namespace std;
// result[i]分别记录n为i时的分子和分母
pair<long long, long long> result[35];
pair<long long,long long> get_result(pair<long long,long long> r1, pair<long long,long long> r2);
long long gcd(long long x, long long y);
int main()
{
// 计算所有情况
for(int i = 1; i <= 33; i++)
{
if(i == 1)
result[i] = pair<long long,long long>(1, 1);
else
{
// 计算两个分数相加的结果
result[i] = get_result(result[i-1], pair<long long,long long>(1, i));
}
}
for(int i = 1; i <= 33; i++)
{
result[i].first = result[i].first * i;
long long x = gcd(result[i].first, result[i].second);
result[i].first = result[i].first / x;
result[i].second = result[i].second / x;
}
// 读入情况
char up_str[100];
char down_str[100];
char int_str[100];
int n;
while(scanf("%d", &n) == 1)
{
// 打印整数和分数部分
long long t_int = result[n].first / result[n].second;
long long t_up = result[n].first % result[n].second;
if(t_up == 0)
printf("%lld\n", t_int);
else
{
memset(up_str, 0, sizeof(up_str));
memset(down_str, 0, sizeof(down_str));
sprintf(up_str, "%lld", t_up);
sprintf(down_str, "%lld", result[n].second);
int len = max(strlen(up_str), strlen(down_str));
if(t_int == 0)
{
printf("%lld\n", t_up);
for(int i = 0; i < len; i++)
printf("-");
printf("\n%lld\n", result[n].second);
}
else
{
memset(int_str, 0, sizeof(int_str));
sprintf(int_str, "%lld", t_int);
int int_len = strlen(int_str);
for(int i = 0; i <= int_len; i++)
printf(" ");
printf("%lld\n", t_up);
printf("%lld ", t_int);
for(int i = 0; i < len; i++)
printf("-");
printf("\n");
for(int i = 0; i <= int_len; i++)
printf(" ");
printf("%lld\n", result[n].second);
}
}
}
return 0;
}
// 计算两个分数相加的结果
pair<long long,long long> get_result(pair<long long,long long> r1, pair<long long,long long> r2)
{
long long now_up = r1.first*r2.second + r2.first*r1.second;
long long now_down = r1.second*r2.second;
long long x = gcd(now_up, now_down);
return pair<long long,long long>(now_up/x, now_down/x);
}
// 计算两数的最大公约数
long long gcd(long long x, long long y)
{
if(x < y)
return gcd(y, x);
else
{
if(y == 0)
return x;
else
return gcd(y, x % y);
}
}
一道经典的概率题。
用到了期望线性性和几何分布的期望。
设Y为收集n个奖券的开包次数
设Yi为收集了i-1个奖券,想要收集到第i个奖券需要的开包次数。
则Y = Y1+Y2+ ... + Yn.
E[Y] = E[Y1+Y2+ ... + Yn] = E[Y1]+E[Y2]+ ... +E[Yn].
由于Yi为几何分布,得到第i个奖券的概率p为(n-(i-1)) / n
E[Yi] = 1/p.
则E[Y] = n/1 + n/2 + n/3 + ... + n/n. 为O(nlogn)