1. 程式人生 > >2018年11月1日提高組 T1 可見點數

2018年11月1日提高組 T1 可見點數

大意

給定一個 n × n n\times n 的點陣,若站在(0,0)這個點問最多能看到多少個點?


思路

30分思路,觀察發現,當 g c

d ( x , y ) = 1 gcd(x,y)=1 時,滿足要求,暴力即可,時間複雜度: O
( n 2 l o g n ) O(n^2logn)

40分思路,利用公式計算斜率,排序判重,時間複雜度: O ( n 2 ) O(n^2)
參考程式碼:

#include<cstdio>
#include<algorithm>
using namespace std;int n,num,m;
double xl[10000001];
signed main()
{
	scanf("%d",&n);if(n==1) return putchar(48)&0;
	if(n==2) return putchar(50)&0;
	for(register int i=1;i<n;i++)
	 for(register int j=1;j<n;j++)
	xl[++num]=i/1.0/j;//計算斜率
	sort(xl+1,xl+1+num);//排序
	m=unique(xl+1,xl+1+num)-xl-1;//去重
	printf("%d",m+2);//輸出
}

100分思路, g c d ( x , y ) = 1 gcd(x,y)=1 ,假設 x y x\geq y ,這種時候就是求 φ ( x ) \varphi(x) 了,最終答案乘2加1即可,其中暴力求 φ ( x ) \varphi(x) 複雜度的複雜度為 O ( n n ) O(n\sqrt{n}) ,線性推複雜度為 O ( n ) O(n)

參考圖:
優秀


程式碼

#include<cstdio>
#include<algorithm>
using namespace std;long long ans,n;
inline long long phi(long long x)//暴力求phi
{
    long long y=x;
    for(long long i=2;(long long)i*i<=x;i++) if(x%i==0) {y=y/i*(i-1);do x/=i;while(x%i==0);}
    if(x>1) y=y/x*(x-1);
    return y;
}
signed main()
{
	scanf("%lld",&n);if(n==1) return putchar(48)&0;
	if(n==2) return putchar(50)&0;
	for(long long i=1;i<n;i++) ans+=phi(i);//求和
	printf("%lld",(ans<<1)+1);//輸出
}