Miller_Robin素数判定和Pollard_rho质因数分解模板

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<ctime>
#define ull unsigned long long
using namespace std;
const int lim=20;
template <typename T>
inline void _read(T& x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9'){if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
ull N,k,T,ph;
ull ksc(ull x,ull y,ull mod){
    x%=mod;y%=mod;
    ull ans=0;
    while(y){
        if(y&1)ans=(ans+x)%mod;
        x<<=1;
        if(x>=mod)x%=mod;
        y>>=1;
    }
    return ans;
}
ull mont(ull x,ull y,ull mod){
    ull ans=1;
    for(x%=mod;y;y>>=1,x=ksc(x,x,mod)){
        if(y&1)ans=ksc(ans,x,mod);
    }
    return ans;
}
ull gcd(ull x,ull y){
    if(x==0)return 1;
    if(x<0)return gcd(-x,y); 
    if(y==0)return x;
    else return gcd(y,x%y);
}
bool check(ull a,ull n,ull x,ull t){
    ull i;
    ull ans=mont(a,x,n);
    ull last=ans;
    for(i=1;i<=t;i++){
        ans=ksc(ans,ans,n);
        if(ans==1&&last!=1&&last!=n-1)return true;
        last=ans;
    }
    if(ans!=1)return true;
    return false;
}
bool miuller_rabin(ull x){
    if(x<2)return false;
    if(x==2||x==3)return true;
    if((x&1)==0)return false;
    ull temp=x-1,t=0;
    while((temp&1)==0){temp>>=1;t++;}
    for(int i=1;i<=lim;i++){
        ull a=rand()%(x-1)+1;
        if(check(a,x,temp,t))return false;
    }
    return true;
}
ull fac[105];
ull Fac[105];
ull JUDGE[105];
ull tot=0,TOT;
ull poullard(ull x,ull c){
    ull i=1,k=2;
    ull x0=rand()%x;
    ull y=x0;
    for(;;){
        i++;
        x0=(ksc(x0,x0,x)+c)%x;
        ull d=gcd(y-x0,x);
        if(d!=1&&d!=x)return d;
        if(y==x0)return x;
        if(i==k){y=x0;k+=k;}
    }
}
void getfac(ull n){
    if(n==1){
        fac[++tot]=1;
        return;
    }
    if(miuller_rabin(n)){
        fac[++tot]=n;
        return;
    }
    ull p=n;
    while(p>=n)p=poullard(p,rand()%(n-1)+1);
    getfac(p);
    getfac(n/p);
}
ull phi(ull x){
    if(x==1)return 1;
    if(miuller_rabin(x))return x-1;
    tot=0;
    ull temp=x,i;
    getfac(x);
    sort(fac+1,fac+1+tot);
    for(i=1;i<=tot;i++){
        if(fac[i]!=fac[i-1]){
            temp=(temp/fac[i])*(fac[i]-1);
        }
    }
    return temp;
}
bool judge(ull x){
    if(x==1){
        if(N==2)return true;
        else return false;
    }
    ull temp=mont(x,ph,N),t;
    int i;
    if(temp!=1)return false;
    for(i=1;i<=TOT;i++){
        if(mont(x,JUDGE[i],N)==1)return false;
    }
    return true;
}
ull hahaha[1005];
int main(){
    srand(time(NULL));
    ull num,i,j,cnt=0;
    bool flag=false;
    cin>>N>>k;
    if(N==1){
        if(k==1){
            cout<<"1";
        }
        else cout<<"-1";
        return 0;
    }
    ph=phi(N);
    tot=0;
    getfac(ph);
    sort(fac+1,fac+1+tot);
    tot=unique(fac+1,fac+1+tot)-fac-1;
    memcpy(Fac,fac,sizeof(fac));
    TOT=tot;
    for(i=1;i<=TOT;i++){
        JUDGE[i]=ph/Fac[i];
    }
    if(k==1){
        for(i=1;i<=min(1000ull,N-1);i++){
            if(judge(i)){
                cout<<i;
                return 0;
            }
        }
        cout<<"-1";
        return 0;
    }
    for(i=1;i<=min(1000ull,N-1);i++){
        if(judge(i)){
            cnt++;
            hahaha[cnt]=i;
            flag=true;
        }
    }
    if(!flag){
        cout<<"-1";
        return 0;
    }
    num=phi(ph);
    if(num<k){
        cout<<"-1";
        return 0;
    }
    if(cnt>=k){
        cout<<hahaha[k];
        return 0;
    }
    else {
        for(i=1001;;i++){
            if(judge(i)){
                cnt++;
                if(cnt==k){
                    cout<<i;
                    //cout<<"time:"<<clock()-T<<endl;
                    return 0;
                }
            }
        }
    }
}
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>

#define ULL unsigned long long 

using namespace std;
const int maxn=10000+5,inf=0x3f3f3f3f;

ULL n,m,k,phin,A[maxn],P[maxn];

inline ULL Mul(ULL A,ULL B,ULL M){
    ULL ans= 0;
    A%=M; B%=M;
    while(B){
        if(B&1)ans+=A;
        if(ans>=M) ans-=M;
        B>>=1;
        A=A+A; if(A>=M)A-=M;
    }
    return ans;
}

inline ULL pow_mod(ULL x,ULL y, ULL M){
    ULL ans=1;
    for(x%=M;y;y>>=1,x=Mul(x,x,M))
        if(y&1) ans=Mul(ans,x,M);
    return ans;
}

inline ULL GCD(ULL A,ULL B){
    return B>0? GCD(B,A%B):A;
}

const int S=20;

inline bool Miller_Robin(ULL n){ //返回n是否为素数 
    int i,j;
    if(n==2) return true;
    if(!(n&1)) return false;
    if(n<=1) return false; 

    ULL t=0,x,y,N=n-1;
    while(!(N&1)) t++,N>>=1;
    for(i=0;i<S;i++){
        ULL a= rand()%(n-1)+1;
        x= pow_mod(a,N,n);
        for(j=1;j<=t;j++){
            y= Mul(x,x,n);
            if(y==1&&x!=1&&x!=n-1) return false;
            x=y;
        }
        if(x!=1) return false;
    }
    return true;
}


ULL Pollard_rho(ULL x,ULL c){
    ULL i=1,k=2;
    ULL x0=rand()%x;
    ULL y=x0;
    for(;;){
        i++;
        x0=(Mul(x0,x0,x)+c)%x;
        ULL d=GCD(y-x0,x);
        if(d!=1&&d!=x)return d;
        if(y==x0)return x;
        if(i==k){y=x0;k+=k;}
    }
}

int rear;
void Divide(ULL n,ULL P[]){
    if(n==1){
        P[++rear]= 1;
        return; 
    }
    if(Miller_Robin(n)){
        P[++rear]=n;
        return ;
    }
    ULL p=n;
    while(p>=n) p= Pollard_rho(p,rand()+1);
    Divide(p,P); Divide(n/p,P);
}

int Factors(ULL n,ULL P[]){
    rear=0;
    Divide(n,P);
    sort(P+1,P+1+rear);
    return unique(P+1,P+1+rear)-P-1;
}

ULL Phi(ULL n){
    int m=Factors(n,A);
    ULL phi= n;
    for(int i=1;i<=m;i++)
        phi= phi/A[i]*(A[i]-1);
    return phi;
}

inline bool IsRoot(ULL x){
    if(x==1) return n==2;
    if(pow_mod(x,phin,n)!=1) return false;
    for(int i=1;i<=m;i++)
        if(pow_mod(x,P[i],n)==1) return false;
    return true;
}

int main(){
    //freopen("data.in","r",stdin);
    //freopen("myans.out","w",stdout);
    srand(156546);
    cin>>n>>k;
    if(n==1||n==2){
        if(k==1) cout<<1<<endl;
        else puts("-1");
        return 0;
    } 
    phin= Phi(n);
    if(k>Phi(phin)){
        puts("-1"); 
        return 0;
    }
    int j,cnt=0;
    m=Factors(phin,P);
    ULL i;
    for(i=1;i<=m;i++)P[i]= phin/P[i];
    for(i=1;;i++){
        if(IsRoot(i)) cnt++;
        if(cnt==k){
            cout<<i<<endl;
            return 0;
        }
        if(i>1024 && cnt==0){
            puts("-1");
            return 0;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值