poj1811(pollard_rho模板)

题目链接: http://poj.org/problem?id=1811

题意: 判断一个数 n (2 <= n < 2^54)是否为质数, 是的话输出 "Prime", 否则输出其第一个质因子.

思路: 大数质因子分解, 直接用 pollard_rho (详情参见: http://blog.csdn.net/maxichu/article/details/45459533) 模板即可.

代码:

  1 #include <iostream>
  2 #include <algorithm>
  3 #define ll long long
  4 using namespace std;
  5
  6 const int MAXN = 1e2;
  7 const int repeat = 8;//repeat为检测次数,判断错误率为4^-repeat,一般8~10就够了
  8
  9 ll get_mult(ll a, ll b, ll c){//返回a*b%c
 10     a %= c;
 11     b %= c;
 12     ll ret = 0;
 13     while(b){
 14         if(b & 1){
 15             ret += a;
 16             if(ret >= c) ret -= c;
 17         }
 18         b >>= 1;
 19         a <<= 1;
 20         if(a >= c) a -= c;
 21     }
 22     return ret;
 23 }
 24
 25 ll get_pow(ll x, ll n, ll mod){//返回x^n%mod
 26     ll ret = 1;
 27     x %= mod;
 28     while(n){
 29         if(n & 1) ret = get_mult(ret, x, mod);
 30         x = get_mult(x, x, mod);
 31         n >>= 1;
 32     }
 33     return ret;
 34 }
 35
 36 //通过 a^(n-1) = 1(mod n) 来判断n是否为素数
 37 //n-1 = x*2^t 中间使用二次探测定理
 38 //是合数返回true,不一定是合数返回false
 39 bool cherk(ll a, ll n, ll x, ll t){
 40     ll ret = get_pow(a, x, n);
 41     ll last = ret;
 42     for(int i = 1; i <= t; i++){
 43         ret = get_mult(ret, ret, n);
 44         if(ret == 1 && last != 1 && last != n - 1) return true;
 45         last = ret;
 46     }
 47     if(ret != 1) return true;
 48     return false;
 49 }
 50
 51 bool Miller_Rabin(ll n){
 52     if(n < 2) return false;
 53     if(n == 2) return true;
 54     if(!(n & 1)) return false;//偶数
 55     ll x = n - 1, t = 0;
 56     while(!(x & 1)){
 57         x >>= 1;
 58         t++;
 59     }
 60     // srand(time(NULL));
 61     for(int i = 0; i < repeat; i++){
 62         ll a = rand() % (n - 1) + 1;
 63         if(cherk(a, n, x, t)) return false;
 64     }
 65     return true;
 66 }
 67
 68 ll factor[MAXN];
 69 int tot;//n的质因子个数
 70
 71 ll get_gcd(ll a, ll b){
 72     ll tmp;
 73     while(b){
 74         tmp = a;
 75         a = b;
 76         b = tmp % b;
 77     }
 78     return a >= 0 ? a : -a;
 79 }
 80
 81 ll pollard_rho(ll x, ll c){//返回x的一个因子
 82     ll i = 1, k = 2;
 83     // srand(time(NULL));
 84     ll x0 = rand() % (x - 1) + 1;
 85     ll y = x0;
 86     while(1){
 87         i++;
 88         x0 = (get_mult(x0, x0, x) + c) % x;
 89         ll d = get_gcd(y - x0, x);
 90         if(d != 1 && d != x) return d;
 91         if(y == x0) return x;
 92         if(i == k){
 93             y = x0;
 94             k += k;
 95         }
 96     }
 97 }
 98
 99 void findfac(ll n, int k){//对n质因分解并将结果保存到factor中
100     if(n == 1) return;
101     if(Miller_Rabin(n)){
102         factor[tot++] = n;
103         return;
104     }
105     ll p = n;
106     int c = k;//c防止死循环
107     while(p >= n){
108         p = pollard_rho(p, c--);
109     }
110     findfac(p, k);
111     findfac(n / p, k);
112 }
113
114 int main(void){
115     ll n;
116     int t;
117     cin >> t;
118     while(t--){
119         cin >> n;
120         if(Miller_Rabin(n)) cout << "Prime" << endl;
121         else{
122             tot = 0;
123             findfac(n, 107);
124             ll sol = factor[0];
125             for(int i = 1; i < tot; i++){
126                 sol = min(sol, factor[i]);
127             }
128             cout << sol << endl;
129         }
130     }
131     return 0;
132 }

时间: 2024-08-08 15:09:15

poj1811(pollard_rho模板)的相关文章

POJ-1811-Prime Test(pollard_rho模板,快速找最小素因子)

题目传送门 sol:Pollard_Rho的模板题,刚看了Pollard_Rho和Miller_Rabin很多原理性的东西看不懂,只是记住了结论勉强能敲代码. Pollard_Rho #include "cstdio" #include "cstdlib" #include "algorithm" #include "ctime" using namespace std; typedef long long LL; LL gc

POJ 2429 GCD &amp; LCM Inverse

设答案为ans1,ans2 ans1=a1*gcd,ans2=a2*gcd,a1,a2互质 gcd*a1*b1=lcm,gcd*a2*b2=lcm a1*b1=lcm=(ans1*ans2)/gcd=a1*a2 综上所诉,a1=b2,a2=b1. 也就是说,ans1=gcd*k1,ans2=gcd*k2 要求k1,k2尽量接近,并且k1,k2互质,并且,k2*k2=lcm/gcd 需要用到Pollard_rho分解质因数,然后暴力搜索寻找k1,k2.用了kuangbin大神的Pollard_rh

[模板] Miller_Rabin和Pollard_Rho

Miller_Rabin 用途 快速($O(slogn)$,s为尝试次数)地判断一个数是否是质数 原理 首先有费马小定理$a^{p-1}=1 (mod\ p)$当p为质数时成立,所以可以随机选择a来以这个式子作为一定的判断依据,但并不是所有合数都不满足这个式子,甚至存在合数对所有的a都不满足这个式子 然后有二次探测定理$a^2=1 (mod p)$,p是奇质数成立当$a=1(mod p)$或$a=p-1(mod p)$ 证明:移项可得$(a-1)(a+1)=0 (mod p)$ 原文地址:htt

POJ1811 Prime Test(miller素数判断&amp;&amp;pollar_rho大数分解)

http://blog.csdn.net/shiyuankongbu/article/details/9202373 发现自己原来的那份模板是有问题的,而且竟然找不出是哪里的问题,所以就用了上面的链接上的一份代码,下面只是寄存一下这份代码,以后打印出来当模板好了. #pragma warning(disable:4996) #include <iostream> #include <cstring> #include <algorithm> #include <c

大数分解,大数判定综合模板

通过poj1811整理这些算法的模板 所有代码如下: 1 #include <iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 using namespace std; 6 #define LL long long 7 const int maxs = 10000000+5; 8 //对于1要外加特判,否则会运行错误 9 //用小素数表做随机种子 10 __int64

POJ 1181 大整数是否为素数以及求大整数的质因数-数论-(Miller_rabin+Pollard_rho)

题意:求一个整数是否是素数,如果不是,则输出它最小的质因数. 分析: 判断一个大整数是否为素数用Miller_rabin算法,求一个大整数的所有质因数用Pollard_rho算法.这题就是直接套模板. 另外这里的gcd和pow_mod不能用一般的方式,T了.代码里我注释掉的就是T了的写法. 代码: #include<iostream> #include<cmath> #include<ctime> #include<cstdio> #include<a

数学#素数判定Miller_Rabin+大数因数分解Pollard_rho算法 POJ 1811&amp;2429

素数判定Miller_Rabin算法详解: http://blog.csdn.net/maxichu/article/details/45458569 大数因数分解Pollard_rho算法详解: http://blog.csdn.net/maxichu/article/details/45459533 然后是参考了kuangbin的模板: http://www.cnblogs.com/kuangbin/archive/2012/08/19/2646396.html 模板如下: //快速乘 (a

Pollard-Rho大整数拆分模板

随机拆分,简直机智. 关于过程可以看http://wenku.baidu.com/link?url=JPlP8watmyGVDdjgiLpcytC0lazh4Leg3s53WIx1_Pp_Y6DJTC8QkZZqmiDIxvgFePUzFJ1KF1G5xVVAoUZpxdw9GN-S46eVeiJ6Q-zXdei 看完后,觉得随机生成数然后和n计算gcd,可以将随机的次数根号一下.思想很叼. 对于里面说的birthday trick,在执行次数上我怎么看都只能减一半.只是把平均分布,变成了靠近0

大素数判断和素因子分解【miller-rabin和Pollard_rho算法】

集训队有人提到这个算法,就学习一下,如果用到可以直接贴模板,例题:POJ 1811 转自:http://www.cnblogs.com/kuangbin/archive/2012/08/19/2646396.html 传说中的随机算法. 效率极高. 可以对一个2^63的素数进行判断. 可以分解比较大的数的因子. 1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<time