用Miller-Rabin算法进行大素数判断以及Pollard-rho算法进行分解的模版
ll pri[]={2,7,61};//用小素数表做随机种子可避免第一类卡米歇尔数的误判
/*
if n < 1,373,653, it is enough to test a = 2 and 3;
if n < 9,080,191, it is enough to test a = 31 and 73;
if n < 4,759,123,141, it is enough to test a = 2, 7, and 61;
if n < 1,122,004,669,633, it is enough to test a = 2, 13, 23, and 1662803;
if n < 2,152,302,898,747, it is enough to test a = 2, 3, 5, 7, and 11;
if n < 3,474,749,660,383, it is enough to test a = 2, 3, 5, 7, 11, and 13;
if n < 341,550,071,728,321, it is enough to test a = 2, 3, 5, 7, 11, 13, and 17.
*/
ll ans[100005],flag;//ans数组记录分解质因数的结果,flag记录质因数的个数,相同的质因数不合并!
ll gcd(ll a,ll b)//非递归,递归的对大数易爆栈
{
while(b)
{
ll c=a%b;
a=b;
b=c;
}
return a;
}
ll multi(ll a,ll b,ll n)//乘法快速幂
{
ll tmp=0;
while(b){
if(b&1){
tmp+=a;
if(tmp>=n)
tmp-=n;
}
a<<=1;
if(a>=n)a-=n;
b>>=1;
}
return tmp;
}
ll multimod(ll a,ll m,ll n)//乘方快速幂
{
ll tmp=1;
a%=n;
while(m)
{
if(m&1) tmp=multi(tmp,a,n);
a=multi(a,a,n);
m>>=1;
}
return tmp;
}
bool Miller_Rabin(ll n)//大数判断
{
if(n<2)
return false;
if(n==2)
return true;
if(!(n&1))
return false;
ll k=0,i,j,m,a;
m=n-1;
while(!(m&1)) m>>=1,k++;
for(i=0;i<3;i++)
{
if(pri[i]>=n)
return true;
a=multimod(pri[i],m,n);
if(a==1) continue;
for(j=0;jif(a==n-1)
break;
a=multi(a,a,n);
}
if(j==k)
return false;
}
return true;
}
ll pollard_rho(ll c,ll n)//寻找因数
{
ll i,x,y,k,d;
i=1;
x=y=rand()%n;
k=2;
do{
i++;
d=gcd(n+y-x,n);
if(d>1&&dreturn d;
if(i==k) y=x,k<<=1;
x=(multi(x,x,n)+n-c)%n;
}while(y!=x);
return n;
}
void rho(ll n)//递归分解
{
if(Miller_Rabin(n))
{
ans[flag]=n;
flag++;
return;
}
ll t=n;
while(t>=n)//这一步是找出一个因数并存入t中,注意找出的因数没有任何确定的大小顺序
t=pollard_rho(rand()%(n-1)+1,n);
rho(t);
rho(n/t);
return;
}
int main()
{
ll n,i;
flag=0;//质因数的个数必须初始化
scanf("%I64d",&n);
rho(n);//分解出n的所有质因数存入ans数组
for(i=0;i"%I64d ",ans[i]);//显示结果
printf("\n");
return 0;
}