1 首先对于这种,有关一次函数的题目,一定要想到求最大公约数,仔细观察会发现,以C君为0点建立坐标系,只要gcd(x,y)>1,就不
能被看见因为前面肯定被挡住了,例如(3,6)前面肯定有(1,2)被挡住了。
2首先明白了这一点,但是此题的数据有40000*40000个点,显然会炸。有大佬用欧拉公式解决,但是我实在看不懂,也不想看,什么时候
学了欧拉公式再来补坑。用的是类似埃式筛法筛质数的方法。
3于是我们可以求出横纵坐标 公约数(不是最大公约数)为 i 的个数为f[i]=(n/i)∗(m/i),记得第一列和第一行特判,然而要记得有些数被筛了
多次,所以要减去以前筛过的部分,例如现在筛4,那么要减去以前筛2的数。复杂度是nlongn我也不知道怎么来的
#include
using namespace std;
int i,j,n,ans,f[40010];
int main()
{
scanf("%d",&n);
if(n==1)//特判
{
printf("0\n");
return 0;
}
ans=(n-1)*(n-1);
n--;
for(i=n;i>1;i--)
{
f[i]=(n/i)*(n/i);
for(j=2*i;j<=n;j=j+i)//筛掉已经筛过的
{
f[i]=f[i]-f[j];
}
ans=ans-f[i];
}
printf("%d",ans+2);//加上两个特判的数
return 0;
}