【POJ1811】【miller_rabin + pollard rho + 快速乘】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 < 2 54).

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

Source

【分析】
模板题
  1 /*
  2 宋代谢逸
  3 《踏莎行·柳絮风轻》
  4 柳絮风轻,梨花雨细。春阴院落帘垂地。碧溪影里小桥横,青帘市上孤烟起。
  5 镜约关情,琴心破睡。轻寒漠漠侵鸳被。酒醒霞散脸边红,梦回山蹙眉间翠。 
  6 */
  7 #include <cstdio>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <cmath>
 11 #include <queue>
 12 #include <vector>
 13 #include <iostream>
 14 #include <string>
 15 #include <ctime>
 16 #define LOCAL
 17 const int MAXN = 100000 + 5;
 18 using namespace std;
 19 typedef long long ll;
 20 ll n, Ans;
 21 
 22 //快速乘
 23 long long multi(long long a, long long b, long long c){
 24     if (b == 0) return 0;
 25     if (b == 1) return a % c;
 26     long long tmp = multi(a, b / 2, c);
 27     if (b % 2 == 0) return (tmp + tmp) % c;
 28     else return (((tmp + tmp) % c) + a) % c;
 29 }
 30 ll pow(ll a, ll b, ll p){
 31     if (b == 1) return a % p;
 32     ll tmp = pow(a, b / 2, p);
 33     if (b % 2 == 0) return (multi(tmp, tmp, p));
 34     else return multi(multi(tmp, tmp, p), (a % p), p);
 35 }
 36 //二次探测
 37 bool Sec_Check(ll a, ll p, ll c){
 38     ll tmp = pow(a, p, c);
 39     if (tmp != 1 && tmp != (c - 1)) return 0;//不通过
 40     if (tmp == (c - 1) || (p % 2 != 0)) return 1;
 41     return Sec_Check(a, p / 2, c);
 42 }
 43 bool miller_rabin(ll n){
 44     ll cnt = 20;
 45     while (cnt--){
 46         ll a = (rand()%(n - 1)) + 1;
 47         if (!Sec_Check(a, n - 1, n)) return 0; 
 48     }
 49     return 1;
 50 }
 51 //int f(int ) {return }
 52 long long gcd(long long a, long long b){return b == 0? a : gcd(b, a % b);}
 53 long long BIGRAND() {return rand() * RAND_MAX + rand();}
 54 long long pollard_rho(long long n, long long c){
 55     long long x, y, d;
 56     long long i = 1, k = 2;  
 57      x = ((double)rand()/RAND_MAX*(n - 2)+0.5) + 1;  
 58     y = x;  
 59     while(1){  
 60         i++;
 61           //注意顺序
 62         x = (multi(x, x, n) % n + c) % n;  
 63         d = gcd(y - x + n, n);  
 64         if(1 < d && d < n) return d;  
 65         if(y == x) return n;  
 66         if(i == k){  
 67             y = x;  
 68             k <<= 1;  
 69         }  
 70     }  
 71 }
 72 //
 73 void find(long long n, long long c){
 74     if (n == 1) return;
 75     if (miller_rabin(n)) {
 76         if (Ans == -1) Ans = n;
 77         else Ans = min(Ans, n);
 78         return ;
 79     }
 80     long long p = n;
 81     while (p >= n) p = pollard_rho(n, c--);
 82     find(p, c);
 83     find(n / p, c);
 84     //return find(p, c) + find(n / p, c);
 85 }
 86 
 87 int main(){
 88     int T;
 89     srand(time(0));
 90     
 91     scanf("%d", &T);
 92     while (T--){
 93         scanf("%lld", &n);
 94         if (n != 1 && miller_rabin(n)) printf("Prime\n");
 95         else {
 96             Ans = -1;
 97             find(n, 15000);
 98             printf("%lld\n", Ans);
 99         }
100     }
101     return 0;
102 }
View Code

 

转载于:https://www.cnblogs.com/hoskey/p/4372649.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值