首先说一下对不是很大的整数n的拆分,首先将2~sqrt(n)的所有素数打表,然后对应素数表一一试除,试除后,如果n>1,此时n也是素因子。
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1164
代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
const int N=300;
int nprime,prime[N];
bool isprime[N];
void doprime()
{
nprime=0;
long long i,j;
for(i=1;i<N;i+=2)
isprime[i]=true;
isprime[2]=true;
long long k=sqrt(1.0*N)+1;
for(i=2;i<N;i++)
{
if(isprime[i])
{
prime[nprime++]=i;
for(j=i*i;j<N;j+=i)
isprime[j]=false;
}
}
}
void solve(int n)
{
vector <int> vt;
int k=sqrt(1.0*n)+1;
int i;
for(i=0;prime[i]<=k;i++)
{
while(n%prime[i]==0)
{
vt.push_back(prime[i]);
n/=prime[i];
}
}
if(n>1)
vt.push_back(n);
if(vt.size()==1)
{
printf("%d\n",vt[0]);
return ;
}
for(i=0;i<vt.size()-1;i++)
printf("%d*",vt[i]);
printf("%d\n",vt[i]);
}
int main()
{
doprime();
int x;
while(cin>>x)
solve(x);
return 0;
}
Pollard rho整数分解法用于对比较大的整数分解。
算法原理:生成两个整数a和b,计算p=gcd(a-b,n),直到p不为1或者a,b出现循环为止,若p=n,则n为质数,否则p为n的一个约数,选取一个小的随机数x1,迭代生成xi=x(i-1)^2+k,一般去k=1,若序列出现循环,则退出,计算p=gcd(xi-1-xi,n),若p=1,返回上一步,直到p>1为止,若p=n,则n为素数,否则p为n的一个约数并递归分解p和n/p。
代码:
#define TIMES 5
#define RHO 501
typedef long long LL;
vector <LL> factor; //将素因子放在factor里面,注意因子是无序的
LL random(LL n)
{
return (LL)((double) rand()/RAND_MAX*n+0.5);
}
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
LL multi(LL a,LL b,LL mod) //a*b%mod
{
LL ans=0;
while(b)
{
if(b&1)
{
ans+=a;
if(ans>mod)
ans-=mod;
}
b>>=1;
a=(a<<1)%mod;
}
return ans;
}
LL kpow(LL a,LL n,LL mod) //a^n%mod
{
LL ans=1;
while(n)
{
if(n&1)
ans=multi(ans,a,mod);
n>>=1;
a=multi(a,a,mod);
}
return ans;
}
bool witness(LL a,LL n) //二次探测 以a为基,n-1=x*2^t,检验n是不是合数
{
LL m=n-1;
LL j=0;
while(! (m&1))
{
j++;
m>>=1;
}
LL x=kpow(a,m,n);
if(x==1 || x==n-1)
return false;
while(j--)
{
x=x*x;
if(x>n)
x%=n;
if(x==n-1)
return false;
}
return true;
}
bool miller_rabin(LL n)
{
if(n<2) return false;
if(n==2) return true;
if(!(n&1)) return false;
for(LL i=1;i<=TIMES;i++)
{
LL a=random(n-2)+1;
if(witness(a,n))
return false;
}
return true;
}
LL pollard_rho(LL n,int c)
{
LL x,y,d,i=1,k=2;
x=random(n-1)+1;
y=x;
while(1)
{
i++;
x=(multi(x,x,n)+c)%n;
d=gcd(y-x+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 k)
{
if(n==1)
return ;
if(miller_rabin(n))
{
factor.push_back(n);
return ;
}
LL p=n;
while(p>=n)
p=pollard_rho(p,k--);
find(p,k);
find(n/p,k);
}