我们发现,任意两个 x,y <=N 内,每个斜率都只有一个点是可见的
我们可以发现,一个斜率 y/x 最先被发现的点(x,y),他的x,y是互质的
那么,以斜率为1的点作为分界线,坐标(x,i) (1<=i<=x),所有第一个被看见的点的i都是和x互质的,等价于求1~x有多少个数与x互质,那么就变成了欧拉函数的定义,筛法求一遍欧拉函数就可以了
由于 上半部分 和下半部分完全对称,那么就不需要做了,只需要*2就可以了
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=100005;
int primes[N],cnt;
bool st[N];
int s[N];
void get_oula(int n)
{
memset(primes,0,sizeof primes);
memset(st,0,sizeof st);
memset(s,0,sizeof s);
cnt=0;
s[1]=1;
for(int i=2;i<=n;i++)
{
if(!st[i]) primes[cnt++]=i,s[i]=i-1;
for(int j=0;primes[j]*i<=n;j++)
{
int t=primes[j]*i;
st[t]=true;
if(i%primes[j]==0)
{
s[t]=primes[j]*s[i];
break;
}
s[t]=(primes[j]-1)*s[i];
}
}
}
int main()
{
int c;
cin>>c;
for(int i=1;i<=c;i++)
{
int n;
cin>>n;
get_oula(n);
int res=0;
for(int i=1;i<=n;i++)
res+=s[i];
res=2*res+1;
cout<<i<<' '<<n<<' '<<res<<endl;
}
return 0;
}