
解题思路:

//示例代码 C++
#include <cstdio>
#include <cmath>
long long n;
long long gcd(long long a,long long b)
//求最大公约数(用于约分和通分)
{
if(!b)
{
return a;
}
return gcd(b,a%b);
}
int getlen(long long a)
//求一个数的位数(用于输出)
{
return (int)(log(a)/log(10))+1;
}
struct frac
{
long long z,m;
int join(long long a,long long b)
//构造一个分数,值为a/b
{
z=a;
m=b;
int y=gcd(z,m);
z/=y;
m/=y;
//上面三步是约分
return 0;
}
frac operator +=(const frac &other)
//加法
{
long long pu=m*other.m/gcd(m,other.m);
//pu是最简公分母
z*=pu/m;
long long otherz=other.z;
otherz*=pu/other.m;
m=pu;
//上面4步是通分
z+=otherz;
//上面这一步是加法
long long y=gcd(m,z);
m/=y;
z/=y;
//上面三步是约分
return *this;
}
int print()
{
long long pzh=z/m;
long long pz=z-(z/m)*m;
//pzh是带分数形式的整数部分,pz是带分数形式的分子
if(pz)
//如果有分子的话,输出分子
{
for(int i=1; i<=getlen(pzh); i++)
{
putchar(' ');
}
printf("%lld\n",pz);
}
printf("%lld",pzh);
//输出整数部分
if(pz)
//如果有分数部分的话,输出分数线和分母
{
for(int i=1; i<=getlen(m); i++)
{
putchar('-');
}
putchar('\n');
for(int i=1; i<=getlen(pzh); i++)
{
putchar(' ');
}
printf("%lld",m);
}
return 0;
}
};
frac ans;
int main()
{
scanf("%lld",&n);
ans.join(0,1);
//求sum(n/i)
for(long long i=1; i<=n; i++)
{
frac x;
x.join(n,i);
ans+=x;
}
ans.print();
putchar('\n');
return 0;
}
参考答案:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
long long a, b, p;
long long gcd(long long a, long long b) //求最大公约数,参与分数计算,使用long long型函数
{ //此GCD函数建议直接背下来,所有输出分数的题全部都要用到
if (b == 0) return a;
return gcd(b, a%b);
}
int main() { //题意为:从n种数中选出n个不同数的期望次数。
int n, i; cin >> n; a = 1; b = 1; //所以第一个球星抽到的概率是1,第n个是1/n。那么我们要从k个到k+1个球星的概率为(n-k)/n,所以期望为n/(n-k)。
for (i = 2; i <= n; i++) { //答案即为ANS=n(1/1+1/2+1/3+....1/n)
a = a*i + b; b *= i;
p = a; a /= gcd(a, b); b /= gcd(p, b);//计算
}
a *= n;
if (a%b == 0)cout << a / b;
else {
cout << a / b; a -= b*(a / b);
cout << '(' << a / gcd(a, b) << '/' << b / gcd(a, b) << ')';//输出
}
system("pause");
return 0;
}