题目:Farey Sums
Time Limit: 2000/1000 MS (Java/Others)
Description
Given a positive integer, N, the sequence of all fractions a / b with (0< a ≤ b), (1 ≤ b ≤ N) and a and b relatively prime, listed in increasing order, is called the Farey Sequence of order N.
For example, the Farey Sequence of order 6 is :
0/1, 1/6, 1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5, 5/6, 1/1
If the denominators of the Farey Sequence of order N are:
b[1], b[2], …, b[K]
then the Farey Sum of order N is the sum of b[i] / b[i+1] from i = 1 to K - 1.
For example, the Farey Sum of order 6 is:
1/6 + 6/5 + 5/4 + 4/3 + 3/5 + 5/2 + 2/5 + 5/3 + 3/4 + 4/5 + 5/6 + 6/1 = 35/2
Write a program to compute the Farey Sum of order N (input).
Input
The first line of input contains a single integer P, (1 ≤ P ≤ 10000), which is the number of data sets that follow. Each data set should be processed identically and independently.
Each data set consists of a single line of input. It contains the data set number, K, followed by the order N (2 ≤ N ≤ 10000), of the Farey Sum that is to be computed.
Output
For each data set there is a single line of output. The single output line consists of the data set number, K, followed by a single space followed by the Farey Sum as a decimal fraction in lowest terms. If the denominator is 1, print only the numerator.
Sample Input
4
1 6
2 15
3 57
4 9999
Sample Output
1 35/2
2 215/2
3 2999/2
4 91180457/2
大致题意:
输入x,列出0~1之间所有的分母从1到x的分数,然后将分数从小到到排序,分母依次为b[1],b[2],b[3],……,b[k]。计算b[i]/b[i+1]的总和。
题解:
起初直接按题意去模拟计算,意料之中的超时,代码如下:
#include<bits/stdc++.h>
using namespace std;
struct node
{
long long a,b;///a分子,b分母
}qq[100000000];
int cmp(node s1,node s2)
{
return s1.a*s2.b<s1.b*s2.a;//将分数从小到大排序
}
int main()
{
int p,k,x,a[10005];
cin>>p;
while(p--)
{
cin>>k>>x;
int v=0;
/*列举出0~1之间所有的分母从1到x的分数*/
for(int i=1;i<=x;i++){ /*分母*/
for(int j=0;j<=i;j++){ /*分子*/
if(__gcd(i,j)==1){ //令__gcd(i,j)==1,即i和j互质,这样可以得
qq[v].a=j,qq[v++].b=i; //到j/i所有的分数且不出现重复,省去去重的操作
//cout<<qq[v-1].a<<"/"<<qq[v-1].b<<endl;
}
}
}
sort(qq,qq+v,cmp);/*将分数从小到大排序*/
double sum=0;
int tt;
if(x%2)tt=1;
else tt=0;
for(int i=0;i<v;i++){
//cout<<qq[i].b<<"/"<<qq[i+1].b<<endl;
sum+=(double)qq[i].b/(double)qq[i+1].b+(double)qq[i+1].b/(double)qq[i].b;
if(qq[i+1].b==2&&(tt==1?qq[i].b==x:qq[i].b==x-1)){
break;
}
}
printf("%d %.0f/2\n",k,2*sum);
}
return 0;
}
正确做法:
具体请看:
https://blog.csdn.net/meopass/article/details/82952087
https://blog.csdn.net/nameofcsdn/article/details/52597478
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e4+3;
int p[MAX];
void get_euler()
{
for (int i=1;i<=MAX;i++)
p[i]=i;
for(int i=2;i<MAX;i++){
if(p[i]==i)
for(int j=i;j<MAX;j+=i){
p[j]=p[j]/i*(i-1);
}
p[i]+=p[i-1];
}
}
int main()
{
int T,k,x,a[10005];
cin>>T;
get_euler();
while(T--)
{
cin>>k>>x;
cout<<k<<' '<<p[x]*3-1<<"/2"<<endl;
}
return 0;
}