BZOJ2904: 平方和

根据拉格朗日四平方和定理
所以最大为4
1的话我们可以直接开一次方
2的话如果可以表示成形如 x2+y2 的形式输出2.这要求该数质因数分解后形如 4k+3 的质因数次数都是偶数.
最后3和4的讨论如果该数可以表示成 4n(8m+7)4n(8m+7) 输出4,否则输出3

分解质因数用Rho MillerRabin

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
char c;
inline void read(ll &a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
#define lowbit(x) ((x)&(-(x)))
const
 int maxn=50000;
bool check[maxn+1];
int  prime[maxn+1];
int tot;
ll factor[101];
int t;
#define LL ll
inline LL mult(LL a,LL b,LL p)
{
    a%=p; b%=p;
    LL t=(a*b-(LL)((double)a/p*b+0.5)*p);
    return t<0?t+p:t;
}

inline ll pow(ll a,ll x,ll mod)
{
    ll res=1,base=a,i;
    for(i=1;i<=x;i<<=1,base=mult(base,base,mod))
      if(i&x)res=mult(res,base,mod);
    return res;
}
inline ll gcd(ll a,ll b)
{
    ll tp;
    while(b)
      {tp=a%b;a=b;b=tp;}
    return a;
}
inline bool Check(ll p)
{
    if(p<=maxn)
      return !check[p];
    if(!(p&1))return false;
    ll a=rand()%p;
    if(pow(a,p-1,p)!=1)return false;
    ll j=lowbit(p-1),m=(p-1)/j,b=rand()%(p-1)+2,v=pow(b,m,p);
    if(v==1)return true;
    j>>=1;
    while(j)
    {
        if(v==p-1||v==1)return true;
        v=mult(v,v,p);
        j>>=1;
    }
    return false;
}

inline ll f(ll a,ll n)
{return mult(a,a,n);}

inline ll Rho(ll n)
{

    if(n==1)return 1;
    ll k=2,x=rand()%n,y=x,p=1,c=rand()%(n-1)+1;
    for(ll i=1;p==1;i++)
    {
        x=(mult(x,x,n)+c)%n;
        p=abs(x-y);
        p=gcd(n,p);
        if(i==k) y=x,k<<=1;
    }
    return p;
}

void fact(ll n)
{
    if(n==1)return;
    if(Check(n))
       factor[++tot]=n;
    else
      {ll p=Rho(n);fact(n/p);fact(p);}
}

inline bool A2(ll n)
{
    tot=0;
    int j,cnt;
    fact(n);
    sort(factor+1,factor+1+tot);
    for(int i=1;i<=tot;i++)
    {
        if((factor[i]&3)==3)
            {j=i;cnt=0;while(factor[i]==factor[j])j++,cnt++;
            if(cnt&1)return false;i=j-1;}
    }
    return true;
}


int main()
{
    int i,j;
        check[1]=true;
    check[0]=true;
    ll k;
    for(i=2;i<maxn;i++)
     {
        if(!check[i]) prime[++tot]=i;
        for(j=1;j<=tot;j++)
          if((k=prime[j]*1ll*i)>maxn)break;
          else if(i%prime[j]==0){check[k]=true;break;}
          else
            check[k]=true;
     }
     ll n;
    ll T;read(T);
    while(T--)
    {
        read(n);
        ll t=sqrt(n);
        if(t*t==n){puts("1");continue;}
        else if(A2(n)){puts("2");continue;}
        else
        {
            while(!(n&3))n>>=2;
            if((n&7)==7)puts("4");else puts("3");
        }

    }
    return 0;
}

你可能感兴趣的:(BZOJ2904: 平方和)