• [HAOI2008]圆上的整点


    [HAOI2008]圆上的整点

    题目链接:链接

    思路

      这道题目,我们先想一想怎么做暴力?我们可以暴力枚举所有点的横坐标,由于这些整数点的横坐标不能超过$2*r$,所以枚举横坐标的时间复杂度是$O(2*r)$,验证的是$O(1)$,总时间复杂度,过不了。

      暴力想到了,我们就要开始想正解了,仔细读题(题目中给的视频可以看一看,视频做的不错),我们可以发现一个他给的式子$x^2+y^2=r^2$,我们可以由这个式子进行推导,过程如下:

      $x^2+y^2=r^2$   $Rightarrow$   $x^2=r^2-y^2 Rightarrow$      $x^2=(r-y)*(r+y) Downarrow$

      我们设$d=gcd(r-y,r+y) Rightarrow$     $x^2=(d*frac{(r-y)}{d})*(d*frac{(r+y)}{d})Downarrow$

      我们再设$A=frac{(r-y)}{d}$    $B=frac{(r+y)}{d} Rightarrow$  $x^2=d^2*A*B$

      我们看,这个式子的左边是平方,右面是一个平方乘上两个互质的数,所以不难想到,这两个数都是两个平方。所以我们可以把$A$替换成$a^2$,把$B$替换成$b^2$,这样式子就变成了$x^2=d^2*a^2*b^2$这个样子。我们再看以前对于$A$和$B$的定义,我们可以看到$a^2=frac{r-y}{d}$和$b^2=frac{r+y}{d}$,这样我们就可以看出来一个性质,$a^2+b^2=frac{2*r}{d}$,如果我们能够知道$d$和$a$之后$O(1)$推出$b$的值,是不是很好?

      既然推出这个式子来了,我们很容易能看出来这是一个枚举题目,我们可以枚举d的值,由于$a^2+b^2=frac{2*r}{d}$,我们可以知道$d$一定是$2*r$的一个约数,所以我们需要用$O(sqrt{n})$,来枚举$d$的值,再知道一个$d$的值的前提下,我们再用上方的式子,用$O(sqrt{sqrt{n}})$的时间,来枚举$a$的值,同时求出$b$的值验证,验证有三条:$b$是否为整数;$b$是否和枚举的$a$互质;$a eq b$。这三个条件如果都满足,则答案加一。由于我们只是枚举了$a<b$的情况,所以我们这只是统计了在第一象限上的点的个数,所以得到的结果要乘以四,又因为我们没有计算坐标轴上的点,且有四个,所以还要加上四。总的时间复杂的为枚举$d$的$O(sqrt{n})$,乘上枚举$a$的$O(sqrt{sqrt{n}})$,再乘上$gcd$验证的$O(log_2^n)$,整体是$O(sqrt{n}*sqrt{sqrt{n}}*log_2^n)$。

    代码

    #include <stdio.h>
    #include <math.h>
    long long n;
    long long ans;
    long long gcd(long long x,long long y)
    {
        if(!y) return x;
        return gcd(y,x%y);
    }
    int main()
    {
        scanf("%lld",&n);
        for(long long i=1;i*i<=2*n;i++)
        {
            if((2*n)%i) continue;
            for(long long a=1;a*a<=i/2;a++)
            {
                long long b=sqrt(i-a*a);
                if(b*b+a*a!=i) continue;
                if(gcd(a,b)!=1||a==b) continue;
                ans++;
            }
            for(long long a=1;a*a<=(2*n)/(2*i);a++)
            {
                long long b=sqrt(2*n/i-a*a);
                if(b*b+a*a!=2*n/i) continue;
                if(gcd(a,b)!=1||a==b) continue;
                ans++;
            }
        }
        printf("%lld",ans*4+4);
    }
  • 相关阅读:
    用GDB调试程序(一)
    Linux编程基础——GDB(设置断点)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(10月12日~10月18日)
    北京Uber优步司机奖励政策(10月19日~10月25日)
    借贷宝人脸识别无需绑卡,需合作者共同冲刺
    王璐首次详解借贷宝诞生历程 直面创业从0到1
    创造信用收入 借贷宝颠覆创新普惠金融
    php中,如何将编译后的代码,反编译回去。
    chrome调试ajax
    提示text还能输入多少字节
  • 原文地址:https://www.cnblogs.com/yangsongyi/p/9085036.html
Copyright © 2020-2023  润新知