3667: Rabin-Miller算法
Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 1278 Solved: 398
[ Submit][ Status][ Discuss]
Description
Input
第一行:CAS,代表数据组数(不大于350),以下CAS行,每行一个数字,保证在64位长整形范围内,并且没有负数。你需要对于每个数字:第一,检验是否是质数,是质数就输出Prime
第二,如果不是质数,输出它最大的质因子是哪个。
Output
第一行CAS(CAS<=350,代表测试数据的组数)
以下CAS行:每行一个数字,保证是在64位长整形范围内的正数。
对于每组测试数据:输出Prime,代表它是质数,或者输出它最大的质因子,代表它是和数
Sample Input
6
2
13
134
8897
1234567654321
1000000000000
2
13
134
8897
1234567654321
1000000000000
Sample Output
Prime
Prime
67
41
4649
5
Prime
67
41
4649
5
HINT
数据范围:
保证cas<=350,保证所有数字均在64位长整形范围内。
Source
题解:Miller_rabbin+Pollard rho
这道题时限卡的丧心病狂,不能用快速乘,否则会TLE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
LL n,mx;
LL mul(LL a,LL b,LL p)
{
/*LL ans=0; LL base=a%p;
while (b) {
if (b&1) ans=(ans+base)%p;
b>>=1;
base=(base+base)%p;
}
return ans;*/
LL tmp=(a*b-(LL)((long double)a/p*b+1e-8)*p);
return tmp<0?tmp+p:tmp;
}
LL quickpow(LL num,LL x,LL p)
{
LL ans=1; LL base=num%p;
while (x) {
if (x&1) ans=mul(ans,base,p);
x>>=1;
base=mul(base,base,p);
}
return ans;
}
bool miller_rabbin(LL n)
{
if (n==2) return true;
if (n<=1||!(n&1)) return false;
LL t=0,a,x,y,u=n-1;
while (!(u&1)) t++,u>>=1;
for (int i=0;i<=10;i++) {
a=rand()*rand()%(n-1)+1;
x=quickpow(a,u,n);
for (int j=0;j<t;j++) {
y=mul(x,x,n);
if (y==1&&x!=1&&x!=n-1) return false;
x=y;
}
if (x!=1) return false;
}
return true;
}
LL gcd(LL x,LL y)
{
LL r;
while (y) {
r=x%y;
x=y; y=r;
}
return x;
}
LL pollard_rho(LL n,LL c)
{
LL k=2;
LL x=rand()%n,y=x,p=1;
for(LL i=1;p==1;i++)
{
x=(mul(x,x,n)+c)%n;
p=y>x?y-x:x-y;
p=gcd(n,p);
if(i==k)y=x,k+=k;
}
return p;
}
void solve(LL n)
{
if (n==1) return;
if (miller_rabbin(n)) {
mx=max(mx,n);
return;
}
LL p=n;
while (p==n) p=pollard_rho(p,rand()%(n-1)+1);
solve(p); solve(n/p);
}
int main()
{
srand(2000001001);
int T; scanf("%d",&T);
while (T--) {
scanf("%lld",&n);
//cout<<n<<endl;
mx=0;
solve(n);
if (mx==n) puts("Prime");
else printf("%lld\n",mx);
}
}