題目:
在一個平面直角座標系的第一象限內,如果一個點(x,y)與原點(0,0)的連線中沒有通過其他任何點,則稱該點在原點處是可見的。
例如,點(4,2)就是不可見的,因爲它與原點的連線會通過點(2,1)。
部分可見點與原點的連線如下圖所示:
3090_1.png
編寫一個程序,計算給定整數N的情況下,滿足0≤x,y≤N的可見點(x,y)的數量(可見點不包括原點)。
輸入格式
第一行包含整數C,表示共有C組測試數據。
每組測試數據佔一行,包含一個整數N。
輸出格式
每組測試數據的輸出佔據一行。
應包括:測試數據的編號(從1開始),該組測試數據對應的N以及可見點的數量。
同行數據之間用空格隔開。
數據範圍
1≤N,C≤1000
輸入樣例:
4
2
4
5
231
輸出樣例:
1 2 5
2 4 13
3 5 21
4 231 32549
題意可以分析得到只要橫縱座標互質就可以成爲可見點,就有暴力做法,直接枚舉橫縱座標,再用gcd判斷是否互質,計數器加加就可以了,但是這樣的做法n^2複雜度,配上多組輸入的話就是 cn方複雜度。就過不了。這裏想到求質數也可以用歐拉函數,sqrt(n)複雜度,降低所用時間。這裏,求出某個數比它小的所有質數後(s),就可以與它組成2s個座標,而這些座標都可以可見,這裏,(0,1),(1,0)(1,1)三個點要分開討論,直接在最後結果加3就可以了,其他的枚舉算出質數後加它的兩倍即可。
c++代碼如下:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int mod = 1e9+7;
const int N = 1010;
//歐拉函數求質數
int phin(int n)
{
int res = n;
for(int i=2;i<=n/i;i++)
if(n%i==0)
{
res = res/i*(i-1);
while(n%i == 0) n/=i;
}
if(n > 1) res = res/n * (n-1);
return res;
}
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a;scanf("%d",&a);
ll con = 0;
//枚舉求質數
for(int i=2;i<=a;i++) con+=phin(i);
printf("%d %d %lld\n",i,a,2*con + 3);
}
return 0;
}
python 3 代碼(纔開始學py):
def phin(x):
res = x
i = 2
while i <= x//i:
if x%i == 0:
res = res//i *(i-1)
while x%i == 0:
x//=i
i+=1
if x > 1:
res = res//x *(x-1)
return res
n = int(input())
for j in range(1,n+1):
a = int(input())
con = 0
for i in range(2,a+1):
con += phin(i)
print("{:d} {:d} {:d}".format(j,a,2*con+3))