• 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 }
  • 相关阅读:
    原生JS回去顶部
    5月31日の勉強レポート
    5月30日の勉強レポート
    (转)日语自我介绍大全
    5月29日の勉強レポート
    5月28日の勉強レポート
    5月27日の勉強レポート
    5月26日の勉強レポート
    5月25日の勉強レポート
    5月24日の勉強レポート
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12667530.html
Copyright © 2020-2023  润新知