Greater New York 2006Visible Lattice Points
题目大意:现在有一个二维坐标系,只有离散的整数坐标上有点。
现在站在N点向周围看去。问能看到多少个点。
假如看到了(2,1),那么(2,1)后边的(4,2)(6,3)…就被挡住
看不到了。
考虑1*1的时候,有三个点(1,0)(1,1)(0,1)。
(1,0)和(0,1)关于(1,1)对称
再看2*2的时候,有个点(1,0)(1,1)(2,1)(0,1)(1,2)
(1,0)和(0,1)关于(1,1)对称
(2,1)和(1,2)关于(1,1)对称
比1*1多了两个点。并且都是关于(1,1)对称,而(2,2)则被(1,1)遮挡住了
所以我们只考虑下三角的情况。得出结果*2+1就是最终答案。
因为同斜率的点都被第一个点盖掉看不到了,所以我们只考虑斜率有多少种就是得出结果了。
1*1的时候,斜率有0
2*2的时候,斜率有0,1/2
3*3的时候,斜率有0,1/2,1/3,2/3
4*4的时候,斜率有0,1/2(2/4),1/3,2/3,1/4,3/4;
5*5的时候,斜率有0,1/2(2/4),1/3,2/3,1/4,3/4,1/5,2/5,3/5,4/5
6*6的时候,斜率有0,1/2(2/4,3/6),1/3(2/6),2/3(4/6),1/4,3/4,1/5,2/5,3/5,4/5,1/6,5/6
可以看出,其实就是求分母小于等于N的真分数有多少
那么就是单纯的欧拉函数了,这里用普通欧拉函数和快速求欧拉函数都可以
参考博文:http://blog.csdn.net/zhang20072844/article/details/8108727
#include<stdio.h> int prime[1010],phi[1001]; bool unprime[1010]; void Euler()//快速求欧拉函数 { int i,j,k = 0; for(i = 2; i <= 1000; i++) { if(!unprime[i]) { prime[k++] = i; phi[i] = i-1; } for(j = 0; j < k && i*prime[j] <= 1000; j++) { unprime[prime[j]*i] = true; if(i % prime[j] != 0) phi[prime[j]*i] = phi[i] * (prime[j]-1); else { phi[prime[j]*i] = phi[i] * prime[j]; break; } } } } int main() { int C,n; Euler(); phi[1]=1; scanf("%d",&C); int kase = 1; while(C--) { scanf("%d",&n); int sum = 0; for(int i = 1;i <= n; i++) sum += phi[i]; printf("%d %d %d\n",kase++,n,2*sum+1); } return 0; }
#include <stdio.h> #include <math.h> int Euler(int n)//普通求欧拉函数 { int i,ret = n; for(i = 2; i <= sqrt(1.0*n); i++) { if(n % i == 0) { ret = ret - ret/i; } while(n % i == 0) n /= i; } if(n > 1) ret = ret - ret/n; return ret; } int main() { int C,n; scanf("%d",&C); int kase = 1; while(C--) { scanf("%d",&n); int sum = 0; for(int i = 1;i <= n; i++) sum += Euler(i); printf("%d %d %d\n",kase++,n,2*sum+1); } }