您的位置:首页 > 其它

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

2016-04-18 18:45 411 查看
题解:JudgeOnline/upload/201604/sol.doc



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
++;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: