通过poj1811整理这些算法的模板
所有代码如下:
#include <iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; #define LL long long const int maxs = 10000000+5; //对于1要外加特判,否则会运行错误 //用小素数表做随机种子 __int64 pri[25] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; __int64 ans[maxs],flag; //ans数组记录分解质因数的结果(没有顺序),flag记录质因数的个数,相同的质因数不合并! //最大公约数 __int64 gcd(__int64 a,__int64 b) { while(b!=0) { __int64 r = a%b; a=b; b=r; } return a; } //乘法快速幂a*b%n,不写连乘是防止相乘时溢出 __int64 multi(__int64 a,__int64 b,__int64 n) { __int64 temp = 0; while(b!=0) { if(b%2==1) { temp+=a; if(temp>=n) temp-=n; } a*=2; if(a>=n) a-=n; b/=2; } return temp; } //乘方快速幂a^n%m __int64 multimod(__int64 a,__int64 n,__int64 m) { __int64 ans=1; while(n!=0) { if(n%2==1) ans=multi(ans,a,m); a=multi(a,a,m); n/=2; } return ans; } //判断大数是否为素数(米勒罗宾算法) //调用multimod(),multi()函数 bool miller_rabin(__int64 n) { if(n<2) return false; if(n==2) return true; if(n%2==0) return false; __int64 k = 0,m,a,i,j; m=n-1; while(m%2==0) { m=m/2; k++; } for(i=0;i<10;i++) { if(pri[i]>=n) return true; a = multimod(pri[i],m,n); if(a==1) continue; for(j=0;j<k;j++) { if(a==n-1) break; a = multi(a,a,n); } if(j==k) return false; } return true; } //寻找因数 __int64 pollard_rho(__int64 c,__int64 n) { __int64 i,x,y,k,d; i=1; x = y = rand()%n; k=2; do { i++; d = gcd(n+y-x,n); if(d>1&&d<n) return d; if(i==k) { y=x; k=k*2; } x = (multi(x,x,n)+n-c)%n; }while(y!=x); return n; } //递归分解,把大整数n分解保存到ans全局数组中,保存的是质因数 //且这些质因数没有保证顺序,也没有排重 void rhoAll(__int64 n) { if(miller_rabin(n)) { ans[flag]=n; flag++; return; } __int64 t = n; while(t>=n) { //随机取出一个因子,不一定是素数,也不确定大小 t = pollard_rho(rand()%(n-1)+1,n); } rhoAll(t); rhoAll(n/t); return; } //返回大整数n最小的质因数 __int64 rho(__int64 n) { if(miller_rabin(n)) return n; __int64 t = n; while(t>=n) { t = pollard_rho(rand()%(n-1)+1,n); } __int64 a = rho(t); __int64 b = rho(n/t); return a<b?a:b; } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--) { flag = 0; __int64 n; scanf("%I64d",&n); if(miller_rabin(n))//是素数 printf("Prime "); else { rhoAll(n);//把大数n分解成质因数 printf("%I64d ",rho(n));//最小的质因数 } for(int i=0;i<flag;i++)//输出这些质因数 printf("%I64d ",ans[i]); } return 0; }