BZOJ2904: 平方和

来源:互联网 发布:mac网页视频怎么全屏 编辑:程序博客网 时间:2024/06/06 12:31

根据拉格朗日四平方和定理
所以最大为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 longchar 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 llinline 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;}
0 0