通过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\n");
else
{
rhoAll(n);//把大数n分解成质因数
printf("%I64d\n",rho(n));//最小的质因数
}
for(int i=0;i<flag;i++)//输出这些质因数
printf("%I64d\n",ans[i]);
}
return 0;
}