• Pollard-rho的质因数分解


    思路:见参考文章(原理我是写不粗来了)

    代码:

    用到了快速幂米勒罗宾素性检验

      1 #include <iostream>
      2 #include <time.h>
      3 #include <map>
      4 using namespace std;
      5 long long an[] = {2,3,5,7,11,13,17,61};
      6 map<long long,int> mp;//存因数和对应出现次数
      7 int num = 0;
      8 long long Random(long long n)//生成0到n之间的整数
      9 {
     10     return (double) rand()/RAND_MAX*n+0.5;//(doubel)rand()/RAND_MAX生成0-1之间的浮点数
     11 }
     12 
     13 
     14 long long q_mod(long long a,long long n,long long p)//快速幂
     15 {
     16     a = a%p;
     17     //首先降a的规模
     18     long long sum = 1;//记录结果
     19     while(n)
     20     {
     21         if(n&1)
     22         {
     23             sum = (sum*a)%p;//n为奇数时单独拿出来乘
     24         }
     25         a = (a*a)%p;//合并a降n的规模
     26         n /= 2;
     27     }
     28     return sum;
     29 }
     30 
     31 
     32 long long q_mul(long long a,long long b,long long p)//大数模
     33 {
     34     long long sum = 0;
     35     while(b)
     36     {
     37         if(b&1)//如果b的二进制末尾是零
     38         {
     39             (sum += a)%=p;//a要加上取余
     40         }
     41         (a <<= 1)%=p;//不断把a乘2相当于提高位数
     42         b >>= 1;//把b右移
     43     }
     44     return sum;
     45 }
     46 
     47 
     48 //Miller-Rabin
     49 bool witness(long long a,long long n)
     50 {
     51     long long d = n-1;
     52     long long r = 0;
     53     while(d%2==0)
     54     {
     55         d/=2;
     56         r++;
     57     }//n-1分解成d*2^r,d为奇数
     58     long long x = q_mod(a,d,n);
     59     //cout << "d " << d << " r " << r << " x " << x << endl;
     60     if(x==1||x==n-1)//最终的余数是1或n-1则可能是素数
     61     {
     62         return true;
     63     }
     64     while(r--)
     65     {
     66         x = q_mul(x,x,n);
     67         if(x==n-1)//考虑开始在不断地往下余的过程
     68         {
     69             return true;//中间如果有一个余数是n-1说明中断了此过程,则可能是素数
     70         }
     71     }
     72     return false;//否则如果中间没有中断但最后是余数又不是n-1和1说明一定不是素数
     73 }
     74 bool miller_rabin(long long n)
     75 {
     76     const int times = 50;//试验次数
     77     if(n==2)
     78     {
     79         return true;
     80     }
     81     if(n<2||n%2==0)
     82     {
     83         return false;
     84     }
     85     for(int i = 0;i<times;i++)
     86     {
     87         long long a = Random(n-2)+1;//1到(n-1)
     88         //cout << a << endl;
     89         if(!witness(a,n))
     90         {
     91             return false;
     92         }
     93     }
     94     return true;
     95 }
     96 
     97 
     98 //求gcd
     99 long long gcd(long long a,long long b)
    100 {
    101     return b==0?a:gcd(b,a%b);
    102 }
    103 
    104 //Pollard-rho
    105 long long Pollard_rho(long long n,long long c)
    106 {
    107     //cout << "n "  << n << " c " << c << endl;
    108     long long i = 1,k = 2;
    109     long long x = Random(n-1)+1;
    110     long long y = x;
    111     while(true)
    112     {
    113         i++;
    114         x = (q_mul(x,x,n)+c)%n;
    115         long long d = gcd(y-x,n);
    116         if(1<d&&d<n)
    117         {
    118             return d;
    119         }
    120         if(x==y)
    121         {
    122             return n;
    123         }
    124         if(i==k)
    125         {
    126             y = x;
    127             k<<=1;
    128         }
    129     }
    130 }
    131 void find(long long n,long long c)
    132 {
    133     if(n==1)//找完了
    134     {
    135         return;
    136     }
    137     if(miller_rabin(n))//找到了质数
    138     {
    139         num++;
    140         mp[n]++;
    141         return;
    142     }
    143     long long p = n;
    144     while(p>=n)//找p的因数
    145     {
    146         p = Pollard_rho(p,c--);//返回p的因数或1或本身
    147     }
    148     find(p,c);//递归地找p的因子
    149     find(n/p,c);
    150 }
    151 int main()
    152 {
    153     long long n;
    154     while(cin >> n)
    155     {
    156         num = 0;
    157         mp.clear();
    158         find(n,2137342);//随机选取的c
    159         cout << n << " = ";
    160         if(mp.empty())
    161         {
    162             cout << n << endl;
    163         }
    164         for(auto ite = mp.begin();ite!=mp.end();ite++)
    165         {
    166             cout << ite->first << "^" << ite->second;
    167             auto i = ite;
    168             if(++i!=mp.end()) //如果不是最后一个
    169             {
    170                 cout << "*";//输出乘号
    171             }
    172         }
    173     }
    174     return 0;
    175 
    176 }

    其他分解质因数的方法:

    朴素算法:枚举从2到n找n的因子,找到了就不断除,除到不能除为止,再找下一个因子。

    为什么保证是素因子,从二开始,假设有二的因子,不断地除直到没有二就能保证二的倍数也没有了。类似于素数筛的思想。

    代码:

     1 map<int,int> mp;
     2 void decom1(int n)
     3 {
     4     for(int i = 2;i<=n;i++)
     5     {
     6         while(n%i==0)
     7         {
     8             mp[i]++;
     9             n /= i;
    10         }
    11     }
    12 }

    参考文章:

    StanleyClinton,大数因数分解Pollard_rho 算法详解,https://blog.csdn.net/maxichu/article/details/45459533

    陶无语,Pollard Rho因子分解算法,https://www.cnblogs.com/dalt/p/8437119.html(讲解原理的多一点,不过至于是否容易理解,嘿嘿)

  • 相关阅读:
    HTML5 与 CSS3 jQuery部分知识总结【转】
    JS中检测数据类型的几种方式及优缺点【转】
    PHP 小数点保留两位【转】
    ES6中的const命令【转】
    bootstrap学习笔记【转】
    让一个元素垂直水平居中的三种方法【转】
    JavaScript笔试必备语句【转】
    网站优化——前端部分【转】
    移动App服务端架构设计
    IE6浏览器常见的bug及其修复方法
  • 原文地址:https://www.cnblogs.com/zhanhonhao/p/11258384.html
Copyright © 2020-2023  润新知