在一個平面直角座標系的第一象限內,如果一個點(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
思路:
題目可以轉換成,能尋找出多少
其中y2,x2均爲非負整數,且x1 = y1 = 0。
且易得y2和x2一定是沒有公約數的,否則將其約去公約數後的點一定在其左下被提前看到。
那麼gcd(x2,y2) = 0。
需要特殊考慮的是(1,0),(0,1),(1,1)這三個點。
不妨設。所以本題轉換成了求2~n內歐拉函數的和,同時這個和要乘以2,再加上一開始的3個點。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1005;
int v[maxn],phi[maxn],prime[maxn];
int sum[maxn];
void euler()
{
int cnt = 0;
for(int i = 2;i <= 1000;i++)
{
if(v[i] == 0)
{
v[i] = i;
phi[i] = i - 1;
prime[++cnt] = i;
}
for(int j = 1;j <= cnt && prime[j] * i < maxn;j++)
{
v[i * prime[j]] = prime[j];
phi[i * prime[j]] = phi[i] * (i % prime[j] ? prime[j] - 1 : prime[j]);
if(i % prime[j] == 0)break;
}
}
}
int main()
{
euler();
int T;scanf("%d",&T);
for(int i = 1;i <= 1000;i++)
{
sum[i] = sum[i - 1] + phi[i];
}
int kase = 0;
while(T--)
{
int n;scanf("%d",&n);
printf("%d %d %d\n",++kase,n,sum[n] * 2 + 3);
}
return 0;
}