【模板】Pollard-Rho分解质因数

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/85050319

参考题目:BZOJ3667


解析:

板子题解析看心情更新

BB:在这份板子里面你看到的所有卡常痕迹都是为了那个毒瘤数据的洛谷版题(虽然最后还是没有过。。。)


UPD:

终于找到洛谷上面过不了的原因了。
新的能过的代码放在最下面,大家可以自己找一下不同,主要是实现的地方比较关键。


代码(洛谷未过):

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define puts put_s
#define cs const

namespace IO{
    cs int Rlen=1<<18|1;
    char buf[Rlen],*p1=buf,*p2=buf;
    char obuf[Rlen],*p3=obuf;
    
    inline char get_char(){
        return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
    }
    
    inline ll getint(){
        re ll num;
        re char c;
        while(!isdigit(c=gc()));num=c^48;
        while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
        return num;
    }
    
    inline void put_char(char c){
        *p3++=c;
        if(p3==obuf+Rlen)fwrite(obuf,1,Rlen,stdout),p3=obuf;
    }
    
    inline void put_s(cs char *s){
        for(int re i=0;s[i];++i)pc(s[i]);pc('\n');
    }
    
    inline void outint(ll a){
        static char ch[23];
        if(a==0)pc('0');
        while(a)ch[++ch[0]]=a-a/10*10,a/=10;
        while(ch[0])pc(ch[ch[0]--]^48);pc('\n');
    }
    
    inline void FLUSH(){
        if(p3==obuf)return ;
        fwrite(obuf,1,p3-obuf,stdout);
        p3=obuf;
    }
}
using namespace IO;

inline ll mul(ll a,ll b,ll mod){
    return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
}

inline ll quickpow(ll a,ll b,ll mod){
    re ll ans=1;
    for(;b;b>>=1,a=mul(a,a,mod))if(b&1)ans=mul(ans,a,mod);
    return ans;
}

cs int P=1007;
bitset<P> mark;
int prime[P],pcnt;
int maxpri[P];
inline void linear_sieves(int len=P-7){
    mark[1]=true;
    for(int re i=2;i<=len;++i){
        if(!mark[i])prime[++pcnt]=i,maxpri[i]=i;
        for(int re j=1;j<=pcnt&&i*prime[j]<=len;++j){
            mark[i*prime[j]]=true;
            maxpri[i*prime[j]]=maxpri[i];
            if(i==i/prime[j]*prime[j])break;
        }
    }
}

inline bool isprime(ll x){
    if(x<=P-7)return !mark[x];
    if(!(x&1)||(x%3==0)||(x%5==0)||(x%7)==0||(x%61==0)||(x%24251)==0)return false;
    ll t=x-1,s=0;
    while(!(t&1))t>>=1,++s;
    for(int re i=1;i<=5;++i){
    	ll p=prime[rand()%pcnt+1]%x;
        ll num=quickpow(p,t,x),pre=num;
        if(x%p==0)return false;
        for(int re j=0;j<s;++j){
            num=mul(num,num,x);
            if(num==1&&pre!=1&&pre!=x-1)return false;
            pre=num;
        }
        if(num!=1)return false;
    }
    return true;
}

inline ll gcd(ll a,ll b){
    if(!a||!b)return a+b;
    re int t=__builtin_ctzll(a|b);
    a>>=__builtin_ctzll(a);
    while(b){
        b>>=__builtin_ctzll(b);
        if(a>b)a^=b,b^=a,a^=b;
        b-=a;
    }
    return a<<t;
}

ll ans;
inline ll Pollard_Rho(ll x){
    if(x%2==0)return 2;
    if(x%3==0)return 3;
    if(x%5==0)return 5;
    if(x%7==0)return 7;
    if(x%61==0)return 61;
    if(x%24251==0)return 24251;
    re ll i=1,k=2,n=rand()%(x-1)+1,m=n,c=rand()%(x-1)+1;
    while(true){
        ++i;
        n=(mul(n,n,x)+c)%x;
        re ll p=gcd((m-n+x)%x,x);
        if(p!=1&&p!=x)return p;
        if(m==n)return x;
        if(i==k)k<<=1,m=n;
    }
}

inline void sieves(ll x){
    if(x==1)return ;if(x<=ans)return ;
    if(isprime(x))return (void)(ans=max(ans,x));
    if(x<=P-4)return (void)(ans=max(ans,(ll)maxpri[x]));
    re ll p=x;
    while(p>=x)p=Pollard_Rho(p);
    sieves(p);
    while(x%p==0)x/=p;
    sieves(x);
}

int T;
signed main(){
    srand(time(0));
    linear_sieves();
    T=getint();
    while(T--){
        ll n=getint();
        if(n<=P-7)mark[n]?outint(maxpri[n]):puts("Prime");
        else {
            ans=0;
            sieves(n);
            if(ans==n)puts("Prime");
            else outint(ans);
        }
    }
    FLUSH();
    return 0;
}

代码:(洛谷已过)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define puts put_s
#define cs const

namespace IO{
    cs int Rlen=1<<18|1;
    char buf[Rlen],*p1=buf,*p2=buf;
    char obuf[Rlen],*p3=obuf;
    
    inline char get_char(){
        return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
    }
    
    inline ll getint(){
        re ll num;
        re char c;
        while(!isdigit(c=gc()));num=c^48;
        while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
        return num;
    }
    
    inline void put_char(char c){
        *p3++=c;
        if(p3==obuf+Rlen)fwrite(obuf,1,Rlen,stdout),p3=obuf;
    }
    
    inline void put_s(cs char *s){
        for(int re i=0;s[i];++i)pc(s[i]);pc('\n');
    }
    
    inline void outint(ll a){
        static char ch[23];
        if(a==0)pc('0');
        while(a)ch[++ch[0]]=a-a/10*10,a/=10;
        while(ch[0])pc(ch[ch[0]--]^48);pc('\n');
    }
    
    inline void FLUSH(){
        if(p3==obuf)return ;
        fwrite(obuf,1,p3-obuf,stdout);
        p3=obuf;
    }
}
using namespace IO;

inline ll mul(ll a,ll b,ll mod){
    return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
}

inline ll quickpow(ll a,ll b,ll mod){
    re ll ans=1;
    for(;b;b>>=1,a=mul(a,a,mod))if(b&1)ans=mul(ans,a,mod);
    return ans;
}

cs int P=1007;
bitset<P> mark;
int prime[P],pcnt;
int maxpri[P];
inline void linear_sieves(int len=P-7){
    mark[1]=true;
    for(int re i=2;i<=len;++i){
        if(!mark[i])prime[++pcnt]=i,maxpri[i]=i;
        for(int re j=1;j<=pcnt&&i*prime[j]<=len;++j){
            mark[i*prime[j]]=true;
            maxpri[i*prime[j]]=maxpri[i];
            if(i==i/prime[j]*prime[j])break;
        }
    }
}

inline bool isprime(ll x){
    if(x<=P-7)return !mark[x];
    if(!(x&1)||(x%3==0)||(x%5==0)||(x%7)==0||(x%61==0)||(x%24251)==0)return false;
    ll t=x-1,s=0;
    while(!(t&1))t>>=1,++s;
    for(int re i=1;i<=5;++i){
    	ll p=prime[rand()%pcnt+1]%x;
        ll num=quickpow(p,t,x),pre=num;
        if(x%p==0)return false;
        for(int re j=0;j<s;++j){
            num=mul(num,num,x);
            if(num==1&&pre!=1&&pre!=x-1)return false;
            pre=num;
        }
        if(num!=1)return false;
    }
    return true;
}

inline ll gcd(ll a,ll b){
    if(!a||!b)return a+b;
    re int t=__builtin_ctzll(a|b);
    a>>=__builtin_ctzll(a);
    while(b){
        b>>=__builtin_ctzll(b);
        if(a>b)a^=b,b^=a,a^=b;
        b-=a;
    }
    return a<<t;
}

ll ans;
inline ll Pollard_Rho(ll x){
    if(x%2==0)return 2;
    if(x%3==0)return 3;
    if(x%5==0)return 5;
    if(x%7==0)return 7;
    if(x%61==0)return 61;
    if(x%24251==0)return 24251;
    ll n=0,m=0,t=1,q=1,c=rand()%(x-1)+1;
    for(ll k=2;;k<<=1,m=n,q=1){
    	for(ll i=1;i<=k;++i){
    		n=(mul(n,n,x)+c)%x;
    		q=mul(q,abs(m-n),x);
        }
        t=gcd(x,q);if(t>1)return t;
    }
}

inline void sieves(ll x){
    if(x==1)return ;if(x<=ans)return ;
    if(isprime(x))return (void)(ans=max(ans,x));
    if(x<=P-7)return (void)(ans=max(ans,(ll)maxpri[x]));
    re ll p=x;
    while(p>=x)p=Pollard_Rho(p);
    sieves(p);
    while(x%p==0)x/=p;
    sieves(x);
}

int T;
signed main(){
    srand(time(0));
    linear_sieves();
    T=getint();
    while(T--){
        ll n=getint();
        if(n<=P-7)mark[n]?outint(maxpri[n]):puts("Prime");
        else {
            ans=0;
            sieves(n);
            if(ans==n)puts("Prime");
            else outint(ans);
        }
    }
    FLUSH();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/85050319