BZOJ4544 椭圆上的整点(数论)

  https://www.cnblogs.com/Gloid/p/9538413.html 基本思路没有太大差别。得到2n=d(a2+3b2),其中d=gcd(n-x,n+x),n-x==a2&&n+x==3b2||n-x==3a2&&n+x==b2。于是枚举d,然后枚举b。复杂度玄学。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
ll gcd(ll n,ll m){return m==0?n:gcd(m,n%m);}
int T;ll n,m;
bool issqr(ll n){return (ll)(sqrt(n))*(ll)(sqrt(n))==n;}
int calc(ll n,ll d)
{
    int s=0;
    for (int i=1;d*i*i<=n;i++)
    {
        ll b=1ll*i*i,a=m/d-b;
        if (a%3==0&&issqr(a/3)&&gcd(a,b)==1) s++;
    }
    for (int i=1;3*d*i*i<=n;i++)
    {
        ll b=3ll*i*i,a=m/d-b;
        if (issqr(a)&&gcd(a,b)==1) s++;
    }
    return s;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj4544.in","r",stdin);
    freopen("bzoj4544.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    T=read();
    while (T--)
    {
        cin>>n;m=n<<1;
        int ans=0;
        for (int d=1;1ll*d*d<=m;d++)
        if (m%d==0)
        {
            ans+=calc(n,d);
            if (m/d!=d) ans+=calc(n,m/d);
        }
        ans*=4;ans+=2;
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2018-11-01 00:53  Gloid  阅读(422)  评论(0编辑  收藏  举报