(Relax 数论 1.5)POJ 1811 Prime Test(MillRabin模板题+Pollard模板题:判定大素数&&合数分解)

来源:互联网 发布:nginx 反向代理 编辑:程序博客网 时间:2024/04/29 22:56
#include <iostream>#include <cstdio>#include <ctime>using namespace std;typedef long long LL;const int maxn = 10000;LL factor[maxn];//用来保存质因子int tot;//用来记录质因子的个数const int S = 20;LL muti_mod(LL a, LL b, LL c) {    //返回(a*b) mod c,a,b,c<2^63a %= 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;}LL pow_mod(LL x, LL n, LL mod) {  //返回x^n mod c ,非递归版if (n == 1) {return x % mod;}int bit[64], k = 0;while (n) {bit[k++] = n & 1;n >>= 1;}LL ret = 1;for (k = k - 1; k >= 0; k--) {ret = muti_mod(ret, ret, mod);if (bit[k] == 1) {ret = muti_mod(ret, x, mod);}}return ret;}bool check(LL a, LL n, LL x, LL t) {   //以a为基,n-1=x*2^t,检验n是不是合数LL ret = pow_mod(a, x, n), last = ret;for (int i = 1; i <= t; i++) {ret = muti_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 = (muti_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;}}}void findfac(LL n) {           //递归进行质因数分解Nif (!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);}int main() {srand(time(NULL));int t;scanf("%d", &t);while (t--) {LL n;scanf("%lld", &n);if (!Miller_Rabin(n)) {printf("Prime\n");} else {tot = 0;findfac(n);LL ans = n;int i;for (i = 0; i < tot; ++i) {ans = min(ans, factor[i]);}printf("%lld\n", ans);}}return 0;}