通过poj1811整理这些算法的模板
所有代码如下:
1 #include <iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 using namespace std; 6 #define LL long long 7 const int maxs = 10000000+5; 8 //对于1要外加特判,否则会运行错误 9 //用小素数表做随机种子 10 __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}; 11 __int64 ans[maxs],flag; 12 //ans数组记录分解质因数的结果(没有顺序),flag记录质因数的个数,相同的质因数不合并! 13 14 //最大公约数 15 __int64 gcd(__int64 a,__int64 b) 16 { 17 while(b!=0) 18 { 19 __int64 r = a%b; 20 a=b; 21 b=r; 22 } 23 return a; 24 } 25 //乘法快速幂a*b%n,不写连乘是防止相乘时溢出 26 __int64 multi(__int64 a,__int64 b,__int64 n) 27 { 28 __int64 temp = 0; 29 while(b!=0) 30 { 31 if(b%2==1) 32 { 33 temp+=a; 34 if(temp>=n) 35 temp-=n; 36 } 37 a*=2; 38 if(a>=n) 39 a-=n; 40 b/=2; 41 } 42 return temp; 43 } 44 //乘方快速幂a^n%m 45 __int64 multimod(__int64 a,__int64 n,__int64 m) 46 { 47 __int64 ans=1; 48 while(n!=0) 49 { 50 if(n%2==1) 51 ans=multi(ans,a,m); 52 a=multi(a,a,m); 53 n/=2; 54 } 55 return ans; 56 } 57 58 //判断大数是否为素数(米勒罗宾算法) 59 //调用multimod(),multi()函数 60 bool miller_rabin(__int64 n) 61 { 62 if(n<2) 63 return false; 64 if(n==2) 65 return true; 66 if(n%2==0) 67 return false; 68 __int64 k = 0,m,a,i,j; 69 m=n-1; 70 while(m%2==0) 71 { 72 m=m/2; 73 k++; 74 } 75 for(i=0;i<10;i++) 76 { 77 if(pri[i]>=n) 78 return true; 79 a = multimod(pri[i],m,n); 80 if(a==1) 81 continue; 82 for(j=0;j<k;j++) 83 { 84 if(a==n-1) 85 break; 86 a = multi(a,a,n); 87 } 88 if(j==k) 89 return false; 90 } 91 return true; 92 } 93 //寻找因数 94 __int64 pollard_rho(__int64 c,__int64 n) 95 { 96 __int64 i,x,y,k,d; 97 i=1; 98 x = y = rand()%n; 99 k=2; 100 do 101 { 102 i++; 103 d = gcd(n+y-x,n); 104 if(d>1&&d<n) 105 return d; 106 if(i==k) 107 { 108 y=x; 109 k=k*2; 110 } 111 x = (multi(x,x,n)+n-c)%n; 112 }while(y!=x); 113 return n; 114 } 115 //递归分解,把大整数n分解保存到ans全局数组中,保存的是质因数 116 //且这些质因数没有保证顺序,也没有排重 117 void rhoAll(__int64 n) 118 { 119 if(miller_rabin(n)) 120 { 121 ans[flag]=n; 122 flag++; 123 return; 124 } 125 __int64 t = n; 126 while(t>=n) 127 { 128 //随机取出一个因子,不一定是素数,也不确定大小 129 t = pollard_rho(rand()%(n-1)+1,n); 130 } 131 rhoAll(t); 132 rhoAll(n/t); 133 return; 134 } 135 136 //返回大整数n最小的质因数 137 __int64 rho(__int64 n) 138 { 139 if(miller_rabin(n)) 140 return n; 141 __int64 t = n; 142 while(t>=n) 143 { 144 t = pollard_rho(rand()%(n-1)+1,n); 145 } 146 __int64 a = rho(t); 147 __int64 b = rho(n/t); 148 return a<b?a:b; 149 } 150 int main() 151 { 152 //freopen("in.txt","r",stdin); 153 int T; 154 scanf("%d",&T); 155 while(T--) 156 { 157 flag = 0; 158 __int64 n; 159 scanf("%I64d",&n); 160 if(miller_rabin(n))//是素数 161 printf("Prime\n"); 162 else 163 { 164 rhoAll(n);//把大数n分解成质因数 165 printf("%I64d\n",rho(n));//最小的质因数 166 } 167 for(int i=0;i<flag;i++)//输出这些质因数 168 printf("%I64d\n",ans[i]); 169 } 170 return 0; 171 }
时间: 2024-08-03 15:38:51