1. 程式人生 > >[數學 拉格朗日四平方和定理 Rho大整數分解] BZOJ 2904 平方和

[數學 拉格朗日四平方和定理 Rho大整數分解] BZOJ 2904 平方和


PS linux下RAND_MAX是2^31!!TLE了快一頁 另一題4522跟著一起T

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(ll &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline ll Random(ll n)
{
//	return (ll)((double)rand()/(RAND_MAX+1)*n);
	return (ll)rand()*rand()%n;
}

inline ll gcd(ll a,ll b)
{
	return b!=0?gcd(b,a%b):a;
}

inline ll Mul(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 b,ll p)
{
	ll t=1;
	for(;b;b>>=1,a=Mul(a,a,p))
		if(b&1)
			t=Mul(t,a,p);
	return t;
} 

inline bool Witness(ll a,ll p,ll s,ll t)
{
	ll x0,x1;
	x0=Pow(a,t,p);
	while (s--)
	{
		x1=Mul(x0,x0,p);
		if (x1==1 && x0!=1 && x0!=p-1)
			return true;
		x0=x1;
	}
	if (x0!=1) return true;
	return false;
}

inline bool Miller(ll p)
{
	if (p<2) return false;
	if (p==2 || p==3) return true;
	if (~p&1) return false;
	if(p%6!=1 && p%6!=5) return false; 
	ll s=0,t=p-1;
	while (~t&1) s++,t>>=1;
	ll a;
	for (int i=1;i<=5;i++)
	{
		a=Random(p-1)+1;
		if (Witness(a,p,s,t))
			return false;
	}
	return true;
}

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

ll n;
map<ll,int> Map;
typedef map<ll,int>::iterator ITER;

void Calc(ll n,ll c)  
{  
    if(n==1) return;  
    if(Miller(n))  
    {  
        Map[n]++;
        return;  
    }  
    ll t=n;  
//    while(t==n) t=rho(n,Random(n-1)+1);
	ll k=c;  
	while(t==n) t=rho(n,k--);  
    Calc(t,c); Calc(n/t,c);  
}


inline int Query(){
	read(n);
	ll Sqr=(ll)sqrt(n);
	if (Sqr*Sqr==n) return 1;
	ll itmp=n;
	while (1)
	{
		if (itmp%8==7) return 4;
		if (itmp%4==0) itmp/=4; else break;
	}
	Map.clear();
	Calc(n,5);
	int flag=0;
	for (ITER it=Map.begin();it!=Map.end() && !flag;it++)
	{
//		printf("%lld %d\n",it->first,it->second);
		if (it->first%4==3 && it->second%2!=0)
			flag=1;
	}
	if (!flag) return 2;
	return 3;
}

int main()
{
	srand(10086);
	ll Q;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(Q);
	while (Q--)
		printf("%d\n",Query());
	return 0;
}