bzoj 3667: Rabin-Miller算法

模板题,但是感觉mul这个函数可能有问题。要不是数据范围是10^18,写快乘就行了。
     
     
     
     
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
 
#define ll long long
#define inf 1e9
#define eps 1e-8
#define md
using namespace std;
ll mx;
ll mul(ll a,ll b,ll p)
{
ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p);
return tmp<0?tmp+p:tmp;
}
 
ll kpow(ll a,ll b,ll p)
{
ll ans=1;
while (b)
{
if (b&1) ans=mul(ans,a,p);
a=mul(a,a,p); b>>=1;
}
return ans%p;
}
 
bool MR(int n,ll r,int s)
{
ll a=abs(rand())%(n-1)+1;
ll pre=kpow(a,r,n);
for (int i=1;i<=s;i++)
{
ll now=mul(pre,pre,n);
if (now==1&&pre!=n-1&&pre!=1) return 0;
pre=now;
}
if (pre!=1) return 0;
return 1;
}
 
bool is_prime(ll x)
{
if (x<2) return 0;
if (x==2) return 1;
if (!(x&1)) return 0;
int s=0; ll r=x-1;
while (!(r&1)) { r>>=1; s++;}
for (int i=0;i<10;i++)
if (!MR(x,r,s)) return 0;
return 1;
}
 
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}
 
ll rho(ll n)
{
ll c=abs(rand())%(n-1)+1,x=abs(rand())%n,y=x;
int k=2;
for (int i=1;;i++)
{
x=(mul(x,x,n)+c)%n;
ll t=gcd(n,(y-x+n)%n);
if (t!=1&&t!=n) return t;
if (x==y) return n;
if (i==k) { k<<=1; y=x;}
}
return n;
}
 
void solve(ll x)
{
if (x==1) return;
if (is_prime(x)) { mx=max(mx,x); return; }
ll t=x;
while (t==x) t=rho(x);
solve(t); solve(x/t);
}
 
int main()
{
int tt;
scanf("%d",&tt);
while (tt--)
{
ll x;
scanf("%lld",&x);
mx=0;
solve(x);
if (mx!=x) printf("%lld\n",mx);
else printf("Prime\n");
}
return 0;
}

你可能感兴趣的:(bzoj 3667: Rabin-Miller算法)