Pollard_rho算法进行质因素分解

Pollard_rho算法进行质因素分解要依赖于Miller_Rabbin算法判断大素数,没有学过的可以看一下,也可以当成模板来用

 

讲一下Pollard_rho算法思想:

求n的质因子的基本过程是,先判断n是否为素数,如果不是则按照一个伪随机数生成过程来生成随机数序列,对于每个生成的随机数判断与n是否互质,如果互质则尝试下一个随机数。如果不互质则将其公因子记作p,递归求解p和n/p的因子。如果n是素数则直接返回n为其素因子。

Pollard rho算法的原理就是通过某种方法得到两个整数a和b,而待分解的大整数为n,计算p=gcd(a-b,n),直到p不为1,或者a,b出现循环为止。然后再判断p是否为n,如果p=n成立,那么返回n是一个质数,否则返回p是n的一个因子,那么我们又可以递归的计算Pollard(p)和Pollard(n/p),这样,我们就可以求出n的所有质因子。

具体操作中,我们通常使用函数x2=x1*x1+c来计算逐步迭代计算a和b的值,实践中,通常取c为1,即b=a*a+1,在下一次计算中,将b的值赋给a,再次使用上式来计算新的b的值,当a,b出现循环时,即可退出进行判断。
 

在实际计算中,a和b的值最终肯定一出现一个循环,而将这些值用光滑的曲线连接起来的话,可以近似的看成是一个ρ型的。
对于Pollard rho,它可以在O(sqrt(p))的时间复杂度内找到n的一个小因子p,可见效率还是可以的,但是对于一个因子很少、因子值很大的大整数n来说,Pollard rho算法的效率仍然不是很好

 

为啥要取两个随机数的差?

对于一个大整数n,我们取任意一个数使得是的质因数的几率很小,但如果取两个数以及

使得它们的差是n的因数的几率就提高了,如果取x1以及x2使得gcd(abs(x1-x2), n) > 1的概率就更高了,这就是Pollard-Rho算法的思想。(概率的增加是因为组合数增加了)

 

为啥要用到Miller_Rabbin算法判断大素数

因为最后结果是n的所有质因子的乘积(这个乘积的形式只会有一种),那么肯定要判断某个数是不是素数,用Miller_Rabbin算法判断大素数判断的话要比普通方法快

 

代码:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<map>
  7 #include<vector>
  8 #include<math.h>
  9 #define mem(a,x) memset(a,x,sizeof(a))
 10 using namespace std;
 11 typedef long long LL;
 12 const int maxn=50005;
 13 const int mod=26;
 14 const int INF=0x3f3f3f3f;
 15 const int Times = 10;
 16 const int N = 5500;
 17 LL ct, cnt;
 18 LL fac[N], num[N];
 19 LL gcd(LL a, LL b)  //求两数最大公因子
 20 {
 21     return b? gcd(b, a % b) : a;
 22 }
 23 LL multi(LL a, LL b, LL m)  //快速乘
 24 {
 25     LL ans = 0;
 26     a %= m;
 27     while(b)
 28     {
 29         if(b & 1)
 30         {
 31             ans = (ans + a) % m;
 32             b--;
 33         }
 34         b >>= 1;
 35         a = (a + a) % m;
 36     }
 37     return ans;
 38 }
 39 LL pow(LL a, LL b, LL m)  //快速幂
 40 {
 41     LL ans = 1;
 42     a %= m;
 43     while(b)
 44     {
 45         if(b & 1)
 46         {
 47             ans = multi(ans, a, m);
 48             b--;
 49         }
 50         b >>= 1;
 51         a = multi(a, a, m);
 52     }
 53     return ans;
 54 }
 55 bool Miller_Rabin(LL n)  //判断n是不是素数
 56 {
 57     if(n == 2) return true;
 58     if(n < 2 || !(n & 1)) return false;
 59     LL m = n - 1;
 60     int k = 0;
 61     while((m & 1) == 0)
 62     {
 63         k++;
 64         m >>= 1;
 65     }
 66     for(int i=0; i<Times; i++)
 67     {
 68         LL a = rand() % (n - 1) + 1;
 69         LL x = pow(a, m, n);
 70         LL y = 0;
 71         for(int j=0; j<k; j++)
 72         {
 73             y = multi(x, x, n);
 74             if(y == 1 && x != 1 && x != n - 1) return false;
 75             x = y;
 76         }
 77         if(y != 1) return false;
 78     }
 79     return true;
 80 }
 81 LL pollard_rho(LL n, LL c)  //大整数分解
 82 {
 83     LL i = 1, k = 2;
 84     LL x = rand() % (n - 1) + 1;
 85     LL y = x;
 86     while(true)
 87     {
 88         i++;
 89         x = (multi(x, x, n) + c) % n;
 90         LL d = gcd((y - x + n) % n, n);
 91         if(1 < d && d < n) return d;
 92         if(y == x) return n;
 93         if(i == k)
 94         {
 95             y = x;
 96             k <<= 1;
 97         }
 98     }
 99 }
100 void find(LL n, int c)  //递归查找大整数n的质因子
101 {
102     if(n == 1) return;
103     if(Miller_Rabin(n))
104     {
105         fac[ct++] = n;
106         return ;
107     }
108     LL p = n;
109     LL k = c;
110     while(p >= n) p = pollard_rho(p, c--);
111     find(p, k);
112     find(n / p, k);
113 }
114 int main()
115 {
116     LL n;
117     while(cin>>n)
118     {
119         ct = 0;
120         find(n, 120);
121         sort(fac, fac + ct);
122         num[0] = 1;
123         int k = 1;
124         for(int i=1; i<ct; i++)
125         {
126             if(fac[i] == fac[i-1])
127                 ++num[k-1];
128             else
129             {
130                 num[k] = 1;
131                 fac[k++] = fac[i];
132             }
133         }
134         cnt = k;
135         for(int i=0; i<cnt; i++)
136             cout<<fac[i]<<"^"<<num[i]<<" ";
137         cout<<endl;
138     }
139     return 0;
140 }

 

posted @ 2020-04-09 16:01  kongbursi  阅读(523)  评论(0编辑  收藏  举报