Description
A lattice point (x, y) in the first quadrant (x and y are integers greater than or equal to 0), other than the origin, is visible from the origin if the line from (0, 0) to (x, y) does not pass through any other lattice point. For example, the point (4, 2) is not visible since the line from the origin passes through (2, 1). The figure below shows the points (x, y) with 0 ≤ x, y ≤ 5 with lines from the origin to the visible points.
Write a program which, given a value for the size, N, computes the number of visible points (x, y) with 0 ≤ x, y ≤ N.
Input
The first line of input contains a single integer C (1 ≤ C ≤ 1000) which is the number of datasets that follow.
Each dataset consists of a single line of input containing a single integer N (1 ≤ N ≤ 1000), which is the size.
Output
For each dataset, there is to be one line of output consisting of: the dataset number starting at 1, a single space, the size, a single space and the number of visible points for that size.
Sample Input
4
2
4
5
231
Sample Output
1 2 5
2 4 13
3 5 21
4 231 32549
这道题的大致意思就是给你一个平面直角坐标系(第一象限),给你一个数N,在这N * N 的矩阵中每一个整数坐标上插着一枚钉子(除(0,0)这个点),让你在原点处看一共能看到多少个钉子,如果一个钉子能被看到说明,其与原点所连的直线上,其前面没有钉子。
思路:经过观察分析,我们可以很容易的方向一个钉子在(x,y)坐标上,如果能够被看到的话,那么gcd(x,y)=1。同时题目给你N * N,图像上的每一个点,它是关于y=x对称的,那么我们只需要统计上半部分或者下半部分就可以了。
这道题可以用两种方法做
1).gcd打表:代码如下
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1005;
int sum[maxn];
int num[maxn];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void init(){
memset(sum,0,sizeof sum);
memset(num,0,sizeof num);
for(int i=1;i<maxn;i++){
for(int j=1;j<=i;j++){
if(gcd(i,j)==1)num[i]++;
}
}
for(int i=1;i<maxn;i++)sum[i]=sum[i-1]+num[i];
}
int main(){
int t;
init();
scanf("%d",&t);
for(int i=1;i<=t;i++){
int n;
scanf("%d",&n);
printf("%d %d %d\n",i,n,sum[n]*2+1);
//这里加1,是因为我在打表的时候我把y=x算了两次。
//然后x==0和y==0的时候没算,所以是sum[n]*2+2-1;
}
}
2).欧拉函数(因为我需要gcd(x,y)==1,所以x和y是互质的,可以用欧拉函数求解,在2~N中各个数的欧拉函数,然后将他们加起来,再加3,就是所得答案):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1005;
int phi[maxn];
int sum[maxn];
void euler(){
for(int i=1;i<maxn;i++){
phi[i]=i;
sum[i]=0;
}
for(int i=2;i<maxn;i++){
if(phi[i]==i)
for(int j=i;j<maxn;j+=i)phi[j]=phi[j]*(i-1)/i;
}
for(int i=2;i<maxn;i++){
sum[i]=sum[i-1]+phi[i];
}
}
int main(){
int t;
scanf("%d",&t);
euler();
for(int i=1;i<=t;i++){
int n;
scanf("%d",&n);
printf("%d %d %d\n",i,n,sum[n]*2+3);
}
}
非常感谢苏学长的帮助。
道阻且长
自己选的路 跪着也要走完