题目链接:http://poj.org/problem?id=3090
从(0,0)向周围看去,能在(N,N)点以内看到的点的个数,假设x,y不是互质的,那么一定存在一个点(x/d,y/d)在(x,y)前面被看到,所以看到的点的x和y 一定是互质的,我们只需要扫描一遍n>=y>x.=2中的y就可以,对于一个y我们只要知道2<=x<y中有多少个数是跟它互质的,就是欧拉函数的前缀和,可以在O(N)时间内用最小质数筛法求出来。最后再对称回去就可以了。
代码:
#include<iostream> #include<cstdio> #include<vector> #include<cstring> using namespace std; #define maxn 1010 int sum[maxn],phi[maxn]; int n; int v[maxn]; vector<int> prime; void get_prime(int n){ memset(v,0,sizeof(v)); for(int i=2;i<=n;i++){ if(!v[i]){ v[i]=i;prime.push_back(i); phi[i]=i-1; } for(int j=0;j<prime.size();j++){ if(prime[j]>v[i] || prime[j]>n/i )break; v[i*prime[j]]=prime[j]; //当p|n 且p^2|n时,phi[n]=phi[n/p]*p //当 当p|n 且p^2不能整除n时,phi[n]=phi[n/p]*(p-1) phi[i*prime[j]] = phi[i]* (i%prime[j]?prime[j]-1:prime[j]); } } } int main(){ get_prime(1008); // for(int i=1;i<=100;i++){ // cout<<phi[i]<<" "; // if((i-1)%10 == 0 && i-1)cout<<endl; // } for(int i=2;i<1008;i++)sum[i]=sum[i-1]+phi[i]; int T=0,num; cin>>num; while(num--){ scanf("%d",&n); printf("%d %d %d ",++T,n,3+2*sum[n]); } }