题意:对于一个大整数,判断是否质数,如果不是质数输出最小质因子。
解法:判断质数使用Miller-Rabin测试,分解质因子使用Pollard-Rho,Miller-Rabin测试用的红书模板,将测试集根据matrix67的博客进行了拓展,不过也可以随机取的样子,Pollard-Rho用的kuangbin的模板。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
LL ans = LLONG_MAX;
LL MUL(LL x, LL n, LL p)//乘法取模
{
LL ret = 0;
LL base = x;
while(n)
{
if(n & 1)
ret = (ret + base) % p;
base = (base + base) % p;
n >>= 1;
}
return ret;
}
LL POW(LL x, LL n, LL p)//快速幂取模
{
LL base = x;
LL ret = 1;
while(n)
{
if(n & 1)
ret = MUL(ret, base, p) % p;
base = MUL(base, base, p) % p;
n >>= 1;
}
return ret;
}
bool test(LL n, LL a, LL d)
{
if(n == 2) return true;
if(n == a) return true;
if((n & 1) == 0) return false;
while(!(d & 1)) d = d >> 1;
LL t = POW(a, d, n);
while((d != n - 1) && (t != 1) && (t != n - 1))
{
t = t * t % n;
d <<= 1;
}
return (t == n - 1 || (d & 1) == 1);
}
bool isPrime(LL n)//Miller-Rabin测试
{
if(n < 2) return false;
LL a[] = {2, 3, 5, 7, 11, 13, 17, 61, 24251};//测试集,据说1e16内的整数都可以
for(int i = 0; i < 9; i++) if(!test(n, a[i], n - 1)) return false;
return true;
}
LL gcd(LL a, LL b)//一开始用的__gcd,后来发现好像有负数参数的样子……只好老老实实手写
{
if(a == 0) return 1LL;
if(a < 0) return gcd(-a, b);
while(b)
{
LL t = a % b;
a = b;
b = t;
}
return a;
}
LL pollardRho(LL x, LL c)
{
LL i = 1, k = 2;
LL x0 = rand() % x;
LL y = x0;
while(1)
{
//cout << i << endl;
i++;
x0 = (MUL(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;}
}
}
void findFac(LL n)
{
if(isPrime(n))
{
//cout << n << endl;
ans = min(ans, n);
return ;
}
LL p = n;
while(p >= n) p = pollardRho(p, rand() % (n - 1) + 1);
findFac(p);
findFac(n / p);
}
int main()
{
int T;
while(~scanf("%d", &T))
{
while(T--)
{
ans = LLONG_MAX;
LL n;
scanf("%lld", &n);
if(isPrime(n))
{
puts("Prime");
continue;
}
findFac(n);
printf("%lld
", ans);
}
}
return 0;
}