Pollard-rho的质因数分解

Posted zhanhonhao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(讲解原理的多一点,不过至于是否容易理解,嘿嘿)

 

以上是关于Pollard-rho的质因数分解的主要内容,如果未能解决你的问题,请参考以下文章

Pollard-Rho学习笔记

大数质因解:浅谈Miller-Rabin和Pollard-Rho算法

分解质因数分解质因数是啥意思? 12分解质因数是??

分解质因数

质因数分解

C++实例 分解质因数