#Pollard-Rho,Miller-Rabin,生日悖论,floyd判圈#BZOJ 4802 欧拉函数 洛谷 4718 【模(mú)板】Pollard-Rho算法

本文介绍了一种高效的素数检测及大整数分解算法,使用了Miller-Rabin素性测试与Pollard's Rho因数分解算法。通过C++实现,展示了如何快速判断一个大数是否为素数,并找到其最大素因数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

dalao的见解
在这里插入图片描述

代码

#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstdlib>
#define rr register
using namespace std;
const double ha=pow(11.0,19/17.0);
const int prime[5]={2,3,7,61,24251};
typedef long long ll; ll mx,n;
inline ll iut(){
	rr ll ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans; 
}
inline void print(ll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline ll mo(ll a,ll b,ll mod){return a+b>=mod?a+b-mod:a+b;}
inline ll mul(ll a,ll b,ll mod){return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;}
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll ksm(ll x,ll y,ll mod){
	rr ll ans=1;
	for (;y;y>>=1,x=mul(x,x,mod))
	    if (y&1) ans=mul(ans,x,mod);
	return ans;
}
inline bool mr(ll n){
	if(n==46856248255981ll||n<2) return 0;
    if(n==2||n==3||n==7||n==61||n==24251) return 1;
    if (!(n&1)||!(n%3)||!(n%7)||!(n%61)||!(n%24251)) return 0;
    rr ll m=n-1; rr int cnt=0;
    while (!(m&1)) m>>=1,++cnt;
	for (rr int i=0;i<5&&prime[i]<n;++i){
		rr ll now=ksm(prime[i],m,n),ls=now;
		for (rr int j=1;j<=cnt;++j){
			now=mul(now,now,n);
			if (now==1&&ls!=1&&ls!=n-1) return 0;
			ls=now;
		}
		if (now!=1) return 0;
	} 
	return 1;
}
inline ll rho(ll n,ll h){
	if (!(n&1)) return 2;
	if (!(n%3)) return 3;
	rr ll x1=(rand()+1)%n,x2=x1,p=1;
	for (rr int k=2;;k<<=1,x2=x1,p=1){
		for (rr int i=1;i<=k;++i){
			x1=mo(mul(x1,x1,n),h,n);
			p=mul(p,x1>x2?x1-x2:x2-x1,n);
			if (!(i&127)){
				rr ll d=gcd(p,n);
				if (d>1) return d;
			}
		}
		rr ll d=gcd(p,n);
		if (d>1) return d;
	}
}
inline void dfs(ll n){
	if (n==1) return;
	if (mr(n)){
		mx=mx>n?mx:n;
		return;
	}
	rr ll t=n;
	while (t==n) t=rho(n,rand()%(n-1)+1);
	while (!(n%t)) n/=t;
	dfs(t),dfs(n);
}
signed main(){
	for (rr int t=iut();t;--t){
	    srand((unsigned)((ll)(new char)*ha));
		mx=0,dfs(n=iut());
		if (mx==n) printf("Prime\n");
		    else print(mx),putchar(10);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值