[POJ 1811]Prime Test

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

题解

Miller-Rabin 素数测试

主要利用费马小定理 $a^{p-1} \equiv 1 \pmod{p}$ ,实现的过程如下:

    1. 计算奇数 $M$ ,使得 $N = 2^r \times M+1$
    2. 选择随机数 $A < N$
    3. 对于任意 $i < r$ ,若 $A^{2^i \times M}~mod~N = N-1$ ,则 $N$ 通过随机数 $A$ 的测试
    4. 或者,若 $A^M~mod~N = 1$ ,则 $N$ 通过随机数 $A$ 的测试
    5. 让 $A$ 取不同的值对 $N$ 进行 $5$ 次测试,若全部通过则判定 $N$ 为素数

而在实际运用中,我们可以直接取 $r = 0$ ,从而省去步骤 $3$ 的测试,提高速度;另外的可以首先用几个小素数对 $N$ 进行测试。除此之外也可以引入“二次探测”的思想,防止Carmichael数 卡。

二次探测:对于一个奇素数 $p$ ,对于关于 $x$ 的同余方程 $x^2 \equiv 1 \pmod{p}$ ,在 $[1, p)$ 上的解仅有 $x = 1$ 及 $x = p-1$ 。

Pollard-Rho 分解大数因子

  1 //It is made by Awson on 2018.1.15
  2 #include <set>
  3 #include <map>
  4 #include <cmath>
  5 #include <ctime>
  6 #include <queue>
  7 #include <stack>
  8 #include <cstdio>
  9 #include <string>
 10 #include <vector>
 11 #include <cstdlib>
 12 #include <cstring>
 13 #include <iostream>
 14 #include <algorithm>
 15 #define LL long long
 16 #define Abs(a) ((a) < 0 ? (-(a)) : (a))
 17 #define Max(a, b) ((a) > (b) ? (a) : (b))
 18 #define Min(a, b) ((a) < (b) ? (a) : (b))
 19 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
 20 using namespace std;
 21 const LL INF = 1e18;
 22 void read(LL &x) {
 23     char ch; bool flag = 0;
 24     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
 25     for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
 26     x *= 1-2*flag;
 27 }
 28 void write(LL x) {
 29     if (x > 9) write(x/10);
 30     putchar(x%10+48);
 31 }
 32 
 33 LL n, ans;
 34 const int prime[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
 35 
 36 LL quick_multi(LL a, LL b, LL p) {
 37     LL ans = 0;
 38     while (b) {
 39     if (b&1) ans = (ans+a)%p;
 40     a = (a+a)%p, b >>= 1;
 41     }
 42     return ans;
 43 }
 44 LL quick_pow(LL a, LL b, LL p) {
 45     LL ans = 1;
 46     while (b) {
 47     if (b&1) ans = quick_multi(ans, a, p);
 48     a = quick_multi(a, a, p), b >>= 1;
 49     }
 50     return ans;
 51 }
 52 bool Miller_Rabin(LL x) {
 53     if (x == 1) return false;
 54     for (int i = 0; i < 10; i++) {
 55     if (x == prime[i]) return true;
 56     if (!(x%prime[i])) return false;
 57     }
 58     LL m = x-1, k = 0;
 59     while (!(m&1)) m >>= 1, ++k;
 60     for (int i = 0; i < 10; i++) {
 61     LL a = rand()%(x-2)+2, pre = quick_pow(a, m, x), y;
 62     for (int j = 0; j < k; j++) {
 63         y = quick_multi(pre, pre, x);
 64         if (y == 1 && pre != 1 && pre != x-1) return false;
 65         pre = y;
 66     }
 67     if (pre != 1) return false;
 68     }
 69     return true;
 70 }
 71 LL gcd(LL a, LL b) {return b ? gcd(b, a%b) : a; }
 72 LL Pollard_Rho(LL x, int c) {
 73     LL i = 1, k = 2, a1, a2;
 74     a1 = a2 = rand()%(x-1)+1;
 75     while (true) {
 76     ++i, a1 = (quick_multi(a1, a1, x)+c)%x;
 77     LL d = gcd(Abs(a1-a2), x);
 78     if (1 < d && d < x) return d;
 79     if (a1 == a2) return x;
 80     if (i == k) a2 = a1, k <<= 1;
 81     }
 82 }
 83 void find(LL x, int c) {
 84     if (x == 1) return;
 85     if (Miller_Rabin(x)) {ans = Min(ans, x); return; }
 86     LL p = x, k = c;
 87     while (p == x) p = Pollard_Rho(x, c--);
 88     find(p, k), find(x/p, k);
 89 }
 90 void work() {
 91     srand(time(0));
 92     LL t; read(t);
 93     while (t--) {
 94     read(n); ans = INF;
 95     if (Miller_Rabin(n)) printf("Prime\n");
 96     else find(n, 120), write(ans), putchar('\n');
 97     }
 98 }
 99 int main() {
100     work();
101     return 0;
102 }

 

posted @ 2018-01-15 09:50  NaVi_Awson  阅读(300)  评论(1编辑  收藏  举报