求最小素因子(pollard-rho)

157 篇文章 0 订阅
#include<cstdio>
#include<cstring>
//#include<ctime>
#include<algorithm>
#define LL long long
using namespace std;

inline LL mul(LL a,LL b,LL c)
{return ((a * b - (LL)((long double)a/c*b+1e-8)*c) % c + c ) % c;}
inline LL gcd(LL a,LL b){ return !b ? a : gcd(b , a % b); }
inline LL Pow(LL a,LL b,LL c){
	LL ret = 1;
	for(;b;b>>=1,a=mul(a,a,c)) if(b&1) ret = mul(ret , a , c);
	return ret;
}
const int base[]={2,3,7,31,61,24251};
inline bool Miller_Rabin(LL x)
{
	if(x<2) return 0;
	for(int i=0;i<6;i++) if(base[i]==x) return 1;
	LL res=x-1,k=0,now=0,pre=0,tim;
	for(;!(res&1);res>>=1,k++);
	for(int i=0;i<6 && base[i] < x;i++)
	{
		pre=Pow(base[i],res,x);
		for(tim=k;tim && pre!=1;tim--,pre=now)
			if((now=mul(pre,pre,x))==1 && pre!=1 && pre!=x-1) return 0;
		if(pre!=1) return 0;
	}
	return 1;
}
inline LL Rho(LL x)
{
	LL a=rand()+1,b=a,i=1,j=1,d=1,tmp=1,c=rand()+3;
	for(;d==1;i++)
	{
		a=mul(a,a,x)+c;
		(a>=x) && (a-=x);
		tmp = mul(tmp , abs(b-a) , x);
		(i==j) && (b=a,j<<=1,d=gcd(tmp,x));
		(!(i&1023)) && (d=gcd(tmp,x));
	}
	return (d==x ? Rho(x) : d);
}
LL Max = 0;
inline void Pollard(LL x,LL tmp=0)
{
	if(x <= Max || x==1) return;
	if(Miller_Rabin(x)){ Max = x;return; }
	Pollard(x/(tmp=Rho(x))),Pollard(tmp);
}

int main()
{
	int T;LL n;
	srand(12345);
	for(scanf("%d",&T);T--;)
	{
		scanf("%lld",&n);
		Max = 0;
		Pollard(n);
		if(Max == n) puts("Prime");
		else printf("%lld\n",Max);
	}
}

Pollard_Rho的实际表现其实很大部分上取决于Rho的速度。。。。

然后你需要写一个短小精悍的Rho。

1:Rho中的判相遇实际上就是取gcd,但是gcd虽然常数小但是也不能忽略那个log,

可以把a-b的积存下来,每隔127或1023次取一次gcd。。。。这个优化是最强的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值