Pollard_rho算法详解传送门
素数判定Miller_Rabin 算法详解传送门
随机算法Pollard_rho分解大整数质因数,随机算法Miller_rabin素数判定。
我理解了一个下午还有一个晚上(特别在debug花费了2个小时),结果犯了一个低级隐形错误,我照着模板改了好几次,都没改出来。最后改出来,心里都崩溃了。
最终是两个if的顺序弄反了。但是我白这两个写反了。
为了避免这种条件(前面的条件会对后面有隐含作用),比如n==2,与后面的n % 2 == 0,说明n != 2 && n % 2 == 0,所以 不如把那个条件写上(n != 2).
if(n == 2){//这两个顺序不能变 ,因为这个条件,会被包含在第二个判断里面但是要先判断
return true;
}
if(n < 2 || n % 2 == 0){//这个判断必须在后面,想哭
return false;
}
#include<iostream>
#include<cstdio>
#include<map>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define per(i,a,b) for(int i=a;i<=b;i++)
typedef long long LL;
const int times = 20;
map<LL,int> mp;
int number = 0;
LL Random(LL n){
return ((double)rand() / RAND_MAX * n + 0.5);
}
LL q_mul(LL a,LL b,LL mod){
LL ans = 0;
while(b > 0){
if(b & 1){
ans = (ans + a) % mod;
}
b >>= 1;
//b /= 2;
a = (a + a) % mod;
}
return ans;
}
LL q_pow(LL a,LL b,LL mod){
LL ans = 1;
while(b > 0){
if(b & 1){
ans = q_mul(ans,a,mod);
}
b >>= 1;
//b /= 2;
a = q_mul(a,a,mod);
}
return ans;
}
LL gcd(LL a,LL b){
return (b == 0) ? a : gcd(b,a % b);
}
bool witness(LL a,LL n){//Miller_rbin()算法的精华所在
LL temp = n - 1;//是n-1
int j = 0;
while(temp % 2 == 0){
temp /= 2;
j++;
}
LL x = q_pow(a,temp,n);//计算a^r
if(x == 1 || x == n-1 ){
return true;
}
while(j--){
x = q_mul(x,x,n);
if(x == n-1){
return true;
}
}
return false;
}
bool Miller_rbin(LL n){
if(n == 2){//这两个顺序不能变 ,因为这个条件,会被包含在第二个判断里面但是要先判断
return true;
}
if(n < 2 || n % 2 == 0){//这个判断必须在后面,想哭
return false;
}
per(i,1,times){
LL a = Random(n - 2) + 1;
if(witness(a,n) == false){
return false;
}
}
return true;
}
LL pollard_rho(LL n,LL c){
LL i = 1,k = 2;
LL x = Random(n-1) + 1;
LL y = x;
while(true){
i++;
x = (q_mul(x,x,n) + c) % n ;
LL d = gcd(y-x,n);
if(1 < d && d < n){
return d;
}
if(y == x){
return n;
}
if(i == k){//一种不清楚的优化
y = x;
k <<= 1;
}
}
}
void find(LL n,LL c){//c是随机因子
if(n == 1){
return ;
}
if(Miller_rbin(n)){
number++;
mp[n]++;
return ;
}
LL p = n;
while(p >= n){
p = pollard_rho(p,c--);
}
find(p,c);
find(n/p,c);
}
int main(){
#ifndef ONLINE_JUDGE
//freopen("a.txt","r",stdin);
#endif
LL n = 0;
while(~scanf("%I64d",&n)){
number = 0;
mp.clear();
LL mi = 2137342;
find(n, mi);
printf("%I64d = ",n);
if(mp.empty()){
printf("%I64d\n",n);
}
map<LL,int>::iterator it ;
for(it = mp.begin();it != mp.end();){
printf("%I64d^%d",it->first,it->second);
if((++it) != mp.end()){
printf(" * ");
}
}
printf("\n");
}
return 0;
}