Prime Test
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 30648 | Accepted: 7880 | |
Case Time Limit: 4000MS |
Description
Given a big integer number, you are required to find out whether it's a prime number.
Input
The first line contains the number of test cases T (1 <= T <= 20 ), then the following T lines each contains an integer number N (2 <= N < 254).
Output
For each test case, if N is a prime number, output a line containing the word "Prime", otherwise, output a line containing the smallest prime factor of N.
Sample Input
2 5 10
Sample Output
Prime 2
题目大意:
给一个数N(2 <= N < 2 ^ 54),判断N是否为素数.
解题思路:
由于N非常大,用普通的素数判断方法不行,所以需要采用Miller-Rabin素数测试,如果是素数直接输出"Prime",如果不是素数,用Pollard rho方法进行整数分解,求出所有的质因数后取其最小的即为所求.
AC代码:
#include<iostream>
#include<ctime>
#include<cstdlib>
#include<cmath>
using namespace std;
const int N = 501;
const int C = 201;
const int Times = 11;
#define MAX ((long long)1<<61)
typedef long long ll;
ll mini;
int ct;
ll res[N];
ll gcd(ll a,ll b)
{
return b == 0 ? a : gcd(b,a % b);
}
ll random(ll n)
{
return (ll) ((double) rand() / RAND_MAX * n + 0.5);
}
ll multi(ll a,ll b,ll m) // a * b % m
{
ll ret = 0;
while(b > 0)
{
if(b & 1)
ret = (ret + a) % m;
b >>= 1;
a = (a << 1) % m;
}
return ret;
}
ll quick_mod(ll a,ll b,ll m)
{
ll ans = 1;
a %= m;
while(b)
{
if(b & 1)
{
ans = multi(ans,a,m);
b--;
}
b /= 2;
a = multi(a,a,m);
}
return ans;
}
bool Witness(ll a,ll n) //判断大的素数
{
ll m = n - 1;
int j = 0;
while(!(m & 1))
{
j++;
m >>= 1;
}
ll x = quick_mod(a,m,n);
if(x == 1 || x == n - 1)
return false;
while(j--)
{
x = x * x % n;
if(x == n - 1)
return false;
}
return true;
}
bool miller_rabin(ll n)
{
if(n < 2) return false;
if(n == 2) return true;
if(!(n & 1)) return false;
for(int i=1;i<=Times;i++)
{
ll a = random(n-2) + 1;
if(Witness(a,n)) return false;
}
return true;
}
ll pollard_rho(ll n,int c) //大数分解因数
{
ll x,y,d,i = 1,k = 2;
x = random(n-1) + 1;
y = x;
while(1)
{
i++;
x = (multi(x,x,n) + c) % n;
d = gcd(y - x,n);
if(1 < d && d < n)
{
return d;
}
if(y == x)
{
return n;
}
if(i == k)
{
y = x;
k <<= 1;
}
}
}
void find(ll n,int k)
{
if(n == 1)
return;
//cout<<"1111"<<endl;
if(miller_rabin(n)) //没进去
{
res[++ct] = n;
//cout<<"1111"<<endl;
if(n < mini)
{
mini = n;
//cout<<mini<<endl;
}
return;
}
ll p = n;
while(p >= n)
{
p = pollard_rho(p,k--);
}
find(p,k);
find(n / p,k);
}
int main()
{
int total;
ll n;
scanf("%d",&total);
while(total--)
{
scanf("%lld",&n);
ct = 0;
mini = MAX;
if(miller_rabin(n))
{
printf("Prime\n");
}
else
{
find(n,C);
printf("%lld\n",mini);
}
}
return 0;
}