洛谷 P2158 [SDOI2008]仪仗队 题解(数论)

题目链接

解题方法

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;
}

你可能感兴趣的:(数论)