pollard_rho分解质因数
题目来源:P4718 【模板】Pollard rho 算法
解题思路:模板题不解释,自己也是基本照着书学思路然后复刻,但是用的知识点是真的多。。。
一开始是想直接单走pollard_rho,用这个来判断素数(只要最后返回的Max_now==n就是素数),写完之后狠狠地TLE了
ll mult_mod(ll a,ll b,ll n){
a%=n;b%=n;
ll ret=0;
while(b){
if(b&1){
ret+=a;
ret%=n;
}
a<<=1;
a%=n;
b>>=1;
}
return ret;
}
ll gcd(ll a,ll b){
if(a<b) swap(a,b);
if(b==0) return a;
else return gcd(b,a%b);
}
ll pollard_rho(ll n){
ll i=1,k=2;
ll x=rand()%n;
ll c=rand()%(n-1)+1;
ll y=x;
while(1){
++i;
x=(mult_mod(x,x,n)+c)%n;
ll d=gcd(llabs(y-x),n);
if(d!=1 && d!=n) return d;
if(y==x) return n;
if(i==k){
y=x;k<<=1;
}
}
}
void Find(ll n){
if(n<Max_now || n<2) return;
if(miller_rabin(n,50)){
Max_now=max(Max_now,n);
return;
}
ll t=n;
while(t>=n) t=pollard_rho(n);
while(n%t==0) n/=t; //一直除到n没有t因子
Find(n);Find(t); //从剔除t因子的n和t里面继续找最大因子
}
pollard_rho分解质因数主要有这三部分
mult_mod用于x平方计算防溢出
gcd求最大公约数
pollard_rho用于生成随机数进行启发然后寻找因子
生成随机数的路径是x[i]=(x[i-1]^2+c)%n,我也不知道为什么,数学证明有点复杂,反正玄学之后可以降低复杂度就对了
但是这样还是不够,超时了
超时的主要原因是素数判断太慢,往前翻书后发现有Miller_Rabin素数测试,含泪拿过来套用了
简单阐述一下miller-rabin的流程:
生成s个随机数,每次进行如下操作
1.判断是否是奇数
2.根据生成的数a,判断(a^(n-1)-1)%n是否为0
3.判断最后得到的解是否为1或n-1
满足以上即为素数
ll fast_pow(ll x,ll y,ll mod){
ll res=1;x%=mod;
while(y){
if(y&1) res=(res*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return res;
}
int witness(ll a,ll n){
ll u=n-1;
int t=0;
while(u&1==0) u>>=1,t++;
ll x1,x2;
x1=fast_pow(a,u,n);
for(int i=1;i<=t;++i){
x2=fast_pow(x1,2,n);
if(x2==1 && x1!=1 && x1!=n-1) return 1;
x1=x2;
}
if(x1!=1) return 1;
return 0;
}
int miller_rabin(ll n,int s){
if(n<2) return 0;
if(n==2) return 1;
if(n%2==0) return 0;
for(int i=0;i<n && i<s;++i){
ll a=rand()%(n-1)+1;
if(witness(a,n)) return 0;
}
return 1;
}
言至于此