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的因子,找到了就不斷除,除到不能除爲止,再找下一個因子。ios
爲何保證是素因子,從二開始,假設有二的因子,不斷地除直到沒有二就能保證二的倍數也沒有了。相似於素數篩的思想。算法
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/45459533dom
陶無語,Pollard Rho因子分解算法,https://www.cnblogs.com/dalt/p/8437119.html(講解原理的多一點,不過至因而否容易理解,嘿嘿)post