模板题,代码留作以后用...
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 10000;
const int S = 20;
LL factor[maxn];
int tot;
//返回(a * b) % c,a,b,c<2^63
LL multi_mod(LL a, LL b, LL c)
{
a %= c;
b %= c;
LL ret = 0;
while(b)
{
if (b & 1)
{
ret += a;
if (ret >= c) ret -= c;
}
a <<= 1;
if(a >= c) a -= c;
b >>= 1;
}
return ret;
}
//返回x^n mod c ,非递归版
LL pow_mod(LL x, LL n, LL mod)
{
LL ret = 1;
while(n)
{
if(n & 1) ret = multi_mod(ret, x, mod);
x = multi_mod(x, x, mod);
n >>= 1;
}
return ret;
}
//以a为基,n-1=x*2^t,检验n是不是合数
bool check(LL a, LL n, LL x, LL t)
{
LL ret = pow_mod(a, x, n), last = ret;
for (int i = 1; i <= t; i++)
{
ret = multi_mod(ret, ret, n);
if (ret == 1 && last != 1 && last != (n-1)) return 1;
last = ret;
}
if (ret != 1) return 1;
return 0;
}
/*素数测试*/
bool Miller_Rabin(LL n)
{
LL x = n - 1, t = 0;
while ((x & 1) == 0) x >>= 1, t++;
bool flag = 1;
if (t >= 1 && (x & 1) == 1)
{
for(int k = 0; k < S; k++)
{
LL a = rand()%(n-1) + 1;
if (check(a, n, x, t))
{
flag = 1; break;
}
flag = 0;
}
}
if (!flag || n == 2) return 0;
return 1;
}
LL gcd(LL a,LL b)
{
if (a == 0) return 1;
if (a < 0) return gcd(-a, b);
while (b)
{
LL t = a % b;
a = b;
b = t;
}
return a;
}
/*大整数素因子分解*/
LL Pollard_rho(LL x, LL c)
{
LL i = 1, x0 = rand() % x, y = x0, k = 2;
while(1)
{
i++;
x0 = (multi_mod(x0, x0, x) + c) % x;
LL d = gcd(y - x0, x);
if (d != 1 && d != x)
{
return d;
}
if (y == x0) return x;
if (i == k)
{
y = x0;
k += k;
}
}
}
//递归进行质因数分解N
void findfac(LL n)
{
if (!Miller_Rabin(n))
{
factor[tot++] = n;
return;
}
LL p = n;
while(p >= n) p = Pollard_rho(p, rand() % (n-1) + 1);
findfac(p);
findfac(n / p);
return ;
}
int main()
{
//freopen("aa.in", "r", stdin);
//freopen("bb.out", "w", stdout);
int T; LL n;
cin >> T;
while(T--)
{
cin >> n;
if (!Miller_Rabin(n))
{
printf("Prime\n");
continue;
}
tot = 0;
findfac(n); //进行大整数的素因子分解
LL ans = factor[0];
for(int i = 1; i < tot; i++)
if(factor[i] < ans)
ans = factor[i];
cout << ans << endl;
}
return 0;
}