【Luogu】P4358密钥破解(Pollard Rho)

  题目链接

  容易发现如果我们求出p和q这题就差不多快变成一个sb题了。

  于是我们就用Pollard Rho算法进行大数分解。

  至于这个算法的原理,emmm

  其实也不是很清楚啦

  

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cctype>
#include<ctime>
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

long long e,n,c;

inline double random(double from,double to){
    return rand()*1.0/RAND_MAX*(to-from)+from;
}

inline long long mul(long long a,long long b,long long mod){
    long long ans=0;
    while(b){
        if(b&1)    ans=(ans+a)%mod;
        a=(a+a)%mod;
        b>>=1;
    }
    return ans;
}

inline long long Pow(long long a,long long b,long long mod){
    long long ans=1;
    while(b){
        if(b&1)    ans=mul(ans,a,mod);
        a=mul(a,a,mod);
        b>>=1;
    }
    return ans;
}

inline long long gcd(long long a,long long b){
    return b==0?a:gcd(b,a%b);
}

long long getprime(long long ret,long long c){
    long long x=random(1,n);
    long long y=x;int k=2,cnt=1;
    while(1){
        x=(mul(x,x,n)+c)%n;
        long long d=gcd((x-y+n)%n,n);
        if(d>1&&d<n)    return d;
        if(x==y)    return n;
        if(++cnt==k){    k<<=1;    y=x;    }
    }
}

void exgcd(long long a,long long b,long long &x,long long &y){
    if(b==0){
        x=1;y=0;
        return;
    }
    exgcd(b,a%b,x,y);
    long long tmp=x;x=y;y=tmp-a/b*y;
}

int main(){
    srand(time(NULL));
    e=read(),n=read(),c=read();
    long long p=n;
    while(p>=n)    p=getprime(n,random(1,n));
    long long q=n/p;
    long long r=(p-1)*(q-1);
    long long ano,d;
    exgcd(e,r,d,ano);
    d=(d+r)%r;
    printf("%lld %lld
",d,Pow(c,d,n));
    return 0;
}
原文地址:https://www.cnblogs.com/cellular-automaton/p/8776553.html