bzoj1041

时间:2019-02-16
本文章向大家介绍bzoj1041,主要包括bzoj1041使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

数学题:x^2+y^2=r^2,已知r求整数解(x,y)的个数

首先考虑x,y>0的时候的个数(ans)

∵  x^2+y^2=r^2 ∴ x^2=r^2-y^2 ∴x^2=(r-y)(r+y)

设d=gcd(r-y,r+y); r-y=d*a^2; r+y=d*b^2; (a<b)

∵x^2=d^2*a^2*b^2 ∴x=d*a*b;

∵2*y=d*(b^2-a^2) ∴y=d*(b^2-a^2)/2;

∵2*r=d*(a^2+b^2)  ∴d为2r的因子

∵2*r/d=a^2+b^2 且a<b  ∴a<r/d

所以我们枚举d,a算出b,判断a,b是否互素,若互素,则满足条件,对答案的贡献++;

最后的答案就是ans*4+4(四个象限+4条坐标轴)

复杂度:均摊的,远远小于logn*sqrt(n)

/**************************************************************

    Problem: 1041

    User: syh0313

    Language: C++

    Result: Accepted

    Time:116 ms

    Memory:1300 kb

****************************************************************/

 

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

using namespace std;

long long n,d,a,b;

int ans;

long long gcd(long long x,long long y)

{

 

    if (x<y) {long long cc=x; x=y; y=cc;}

    long long r=x%y;

    while (r) {x=y; y=r; r=x%y;}

return y;

}

void work(long long k)

{

    for (a=1;a*a<n/k;a++)

    {      

        long long now=(2ll*n)/k-a*a;

        b=sqrt(now);

        if (b*b!=now) continue;

        if (gcd(a,b)==1ll)

        {

            //printf("%lld %lld  %lld %lld %lld\n",d*a*b,d*(b*b-a*a)/2,d,a,b);

            ans++;

        }

    }

}

int main()

{

    scanf("%lld",&n);

    for (d=1;d*d<=2*n;d++)

    {

        if ((2ll*n)%d!=0) continue;

        work(d); work(2ll*n/d);

    }

    printf("%d\n",ans*4+4);

return 0;

}