Pollard-Rho模板

P4718 【模板】Pollard-Rho算法

这里有两个模板

第一个是我的,要开O2才能卡过去,慎用

建议用第二个

#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define re register int
#define void inline void
#define eps 1e-18
//#define mod 1e9+7
//#define ls(p) p<<1
//#define rs(p) p<<1|1
//#define ls(p) e[p].l
//#define rs(p) e[p].r
//#define pi acos(-1.0)
#define pb push_back
//#define P pair < int , int >
#define mk make_pair
#define fi first
#define se second
using namespace std;
//const int mod=998244353;
const int M=1e8+5;
const int N=8e6+5;//?????????? 4e8.
ll prime[]={2,61,97,7,13,17,23,29},ans=-1;
inline ll guisumul(ll a,ll b,ll m)
{
    ll d=((long double)a/m*b+1e-8) ;
    ll r=a*b-d*m;
    return r<0?r+m:r;
} 
ll mul(ll a,ll b,ll mod)
{
	ll res=0;
	while(b)
	{
		if(b&1)  res=(res+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	return res;
}
ll power(ll a,ll b,ll mod)
{
	if(a==1)  return 1;
	ll sum=1;
	while(b)
	{
		if(b&1)  sum=mul(sum,a,mod);
		a=mul(a,a,mod);
		b>>=1;
	}
	return sum;
}
bool test(ll p,ll x)
{
    ll r=0,d=x-1;
    while(!(d&1))  d>>=1,++r;
    for(ll i=power(p,d,x),j;r;--r)
	{
        j=mul(i,i,x);
        if(j==1)
		{
            if(i==1||i==x-1)  return 1; 
            return 0;
        }
        i=j;
    }
    return 0 ;
}
#define ctz __builtin_ctzll
ll gcd(ll a,ll b)
{
	if(!a)  return b;
	if(!b)  return a;
	re t=ctz(a|b);
	a>>=ctz(a);
	do
	{
		b>>=ctz(b);
		if(a>b)   swap(a,b);
		b-=a;
	}while(b);
	return a<<t;
}
bool Miller_Rabin(ll x)
{
    if (x==prime[1]||x==prime[0])  return 1;
    if (!(x%prime[1])||!(x%prime[0]))  return 0;
    if (test(prime[1],x)^1)  return 0;
    if (test(prime[0],x)^1)  return 0;
	if (x==prime[2]||x==prime[3])  return 1;
    if (!(x%prime[2])||!(x%prime[3]))  return 0;
    if (test(prime[2],x)^1)  return 0;
    if (test(prime[3],x)^1)  return 0;
	if (x==prime[4]||x==prime[5])  return 1;
    if (!(x%prime[4])||!(x%prime[5]))  return 0;
    if (test(prime[4],x)^1)  return 0;
    if (test(prime[5],x)^1)  return 0;
	if (x==prime[6]||x==prime[7])  return 1;
    if (!(x%prime[6])||!(x%prime[7]))  return 0;
    if (test(prime[6],x)^1)  return 0;
    if (test(prime[7],x)^1)  return 0;
    return 1;
}
ll lrand(ll x)
{
	return 1ll*((rand()<<15^rand())<<30^(rand()<<15^rand()))%x ;
}
ll qwq(ll x)
{
//	cout<<x<<endl;
    ll C=lrand(x);
    ll t1=lrand(x),t2=guisumul(t1,t1,x)+C;
    ll dif=t1>t2?(t1-t2):(t2-t1);
	ll G=gcd(x,dif);
    while(G==1)
	{
        t1=guisumul(t1,t1,x)+C;
		if(t1>=x)  t1%=x;
        t2=guisumul(t2,t2,x)+C,t2=guisumul(t2,t2,x)+C ;
        if(t2>=x)  t2%=x;
		dif=t1>t2?(t1-t2):(t2-t1);
		G=gcd(x,dif) ;
    }
//    cout<<G<<endl;
    return G;
}
void Pollard_Pho(ll x)
{
	if(x==1)  return;
	if(Miller_Rabin(x))
	{
		ans=max(ans,x);
		return;
	}
	ll y=x;
	while(y==x)  y=qwq(x);
	Pollard_Pho(y);
	Pollard_Pho(x/y) ;
}
ll n;
void solve()
{
	ans=-1;
	cin>>n;
	Pollard_Pho(n);
	if(ans==n)  puts("Prime");
	else  printf("%lld\n",ans);
}
signed main()
{
//	freopen("P1505_1.txt", "r", stdin);
//	freopen("Aout.txt", "w", stdout);
    int T=1;
    cin>>T;
	srand(998244353);
    for(int index=1;index<=T;index++)
    {
//        printf("Case #%lld: ",index);
        solve();
//        puts("");
    }
    return 0;
}
/*

10 5
hbtngdflmj
1 10 1
2 9 0
3 8 1
4 7 0
5 6 1


*/
#include<bits/stdc++.h>
using namespace std;
#define rg register
#define RP(i,a,b) for(register int i=a;i<=b;++i)
#define DRP(i,a,b) for(register int i=a;i>=b;--i)
#define fre(z) freopen(z".in","r",stdin),freopen(z".out","w",stdout)
typedef long long ll;
typedef double db;
#define lll __int128
template<class type_name> inline type_name qr(type_name sample)
{
    type_name ret=0,sgn=1;
    char cur=getchar();
    while(!isdigit(cur))
        sgn=(cur=='-'?-1:1),cur=getchar();
    while(isdigit(cur))
        ret=(ret<<1)+(ret<<3)+cur-'0',cur=getchar();
    return sgn==-1?-ret:ret;
}

ll max_factor;

inline ll gcd(ll a,ll b)
{
    if(b==0)
        return a;
    return gcd(b,a%b);
}

inline ll qp(ll x,ll p,ll mod)
{
    ll ans=1;
    while(p)
    {
        if(p&1)
            ans=(lll)ans*x%mod;
        x=(lll)x*x%mod;
        p>>=1;
    }
    return ans;
}

inline bool mr(ll x,ll b)
{
    ll k=x-1;
    while(k)
    {
        ll cur=qp(b,k,x);
        if(cur!=1 && cur!=x-1)
            return false;
        if((k&1)==1 || cur==x-1)
            return true;
        k>>=1;
    }
    return true;
}

inline bool prime(ll x)
{
    if(x==46856248255981ll || x<2)
        return false;
    if(x==2 || x==3 || x==7 || x==61 || x==24251)
        return true;
    return mr(x,2)&&mr(x,61);
}

inline ll f(ll x,ll c,ll n)
{
    return ((lll)x*x+c)%n;
}

inline ll PR(ll x)
{
    ll s=0,t=0,c=1ll*rand()%(x-1)+1;
    int stp=0,goal=1;
    ll val=1;
    for(goal=1;;goal<<=1,s=t,val=1)
    {
        for(stp=1;stp<=goal;++stp)
        {
            t=f(t,c,x);
            val=(lll)val*abs(t-s)%x;
            if((stp%127)==0)
            {
                ll d=gcd(val,x);
                if(d>1)
                    return d;
            }
        }
        ll d=gcd(val,x);
        if(d>1)
            return d;
    }
}

inline void fac(ll x)
{
    if(x<=max_factor || x<2)
        return;
    if(prime(x))
    {
        max_factor=max_factor>x?max_factor:x;
        return;		
    }
    ll p=x;
    while(p>=x)
        p=PR(x);
    while((x%p)==0)
        x/=p;
    fac(x),fac(p);
}

int main()
{
    int T=qr(1);
    while(T--)
    {
        srand((unsigned)time(NULL));
        ll n=qr(1ll);
        max_factor=0;
        fac(n);
            if(max_factor==n)
                puts("Prime");
            else
                printf("%lld\n",max_factor);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值