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}$ ,实现的过程如下:
- 计算奇数 $M$ ,使得 $N = 2^r imes M+1$
- 选择随机数 $A < N$
- 对于任意 $i < r$ ,若 $A^{2^i imes M}~mod~N = N-1$ ,则 $N$ 通过随机数 $A$ 的测试
- 或者,若 $A^M~mod~N = 1$ ,则 $N$ 通过随机数 $A$ 的测试
- 让 $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 "); 96 else find(n, 120), write(ans), putchar(' '); 97 } 98 } 99 int main() { 100 work(); 101 return 0; 102 }