首先低于一般范围的整数分解,我们可以打一个素数表然后用试除的方法对其进行质因子分解。
具体实现代码如下:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define N 65555 bool p[N]; int prime[N],num=0; void init() { memset(p,true,sizeof(p)); for(int i=2;i<N;i++) if(p[i]) { prime[num++]=i; for(int j=i+i;j<N;j+=i) p[j]=0; } } int main() { init(); int n,ans[100]; while(scanf("%d",&n)!=-1) { int cnt=0; for(int i=0;i<num&&prime[i]*prime[i]<=n;i++) { if(n%prime[i]==0) { n/=prime[i]; ans[cnt++]=prime[i]; while(n%prime[i]==0) { n/=prime[i]; ans[cnt++]=prime[i]; } } } if(n!=1) ans[cnt++]=n; for(int i=0;i<cnt-1;i++) printf("%d*",ans[i]); printf("%d\n",ans[cnt-1]); } return 0; }
但如果要对比较大的整数分解,上述方法便失去了实用价值。我们引入Pollard-rho整数分解的方法。
算法原理:生成两个整数a和b,计算p=gcd(a-b,n),直到p不为1或者a,b出现循环为止,若p=n,则p为质数,否则p为n的一个约数。选取一个小的随机数x1,迭代生成xi=xi-1 ^2+k,一般取k=1,若序列出现循环则退出。计算p=gcd(xi-1 - xi,n),若p=1,返回上一步,直到p>1为止。若p=n,则n为素数,否则p为n的一个约数并递归分解p和n/p.
实现代码如下:
#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <stdio.h> const int Times = 10; const int N = 5500; using namespace std; typedef long long LL; LL ct, cnt; LL fac[N], num[N]; LL gcd(LL a, LL b) { return b? gcd(b, a % b) : a; } LL multi(LL a, LL b, LL m) { LL ans = 0; a %= m; while(b) { if(b & 1) { ans = (ans + a) % m; b--; } b >>= 1; a = (a + a) % m; } return ans; } LL quick_mod(LL a, LL b, LL m) { LL ans = 1; a %= m; while(b) { if(b & 1) { ans = multi(ans, a, m); b--; } b >>= 1; a = multi(a, a, m); } return ans; } bool Miller_Rabin(LL n) { if(n == 2) return true; if(n < 2 || !(n & 1)) return false; LL m = n - 1; int k = 0; while((m & 1) == 0) { k++; m >>= 1; } for(int i=0; i<Times; i++) { LL a = rand() % (n - 1) + 1; LL x = quick_mod(a, m, n); LL y = 0; for(int j=0; j<k; j++) { y = multi(x, x, n); if(y == 1 && x != 1 && x != n - 1) return false; x = y; } if(y != 1) return false; } return true; } LL pollard_rho(LL n, LL c) { LL i = 1, k = 2; LL x = rand() % (n - 1) + 1; LL y = x; while(true) { i++; x = (multi(x, x, n) + c) % n; LL d = gcd((y - x + n) % n, n); if(1 < d && d < n) return d; if(y == x) return n; if(i == k) { y = x; k <<= 1; } } } void find(LL n, int c) { if(n == 1) return; if(Miller_Rabin(n)) { fac[ct++] = n; return ; } LL p = n; LL k = c; while(p >= n) p = pollard_rho(p, c--); find(p, k); find(n / p, k); } int main() { LL n; while(cin>>n) { ct = 0; find(n, 120); sort(fac, fac + ct); num[0] = 1; int k = 1; for(int i=1; i<ct; i++) { if(fac[i] == fac[i-1]) ++num[k-1]; else { num[k] = 1; fac[k++] = fac[i]; } } cnt = k; for(int i=0; i<cnt; i++) cout<<fac[i]<<"^"<<num[i]<<" "; cout<<endl; } return 0; }