zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    Linux双线双网卡双IP双网关设置方法
    Docker 清理命令集锦
    Centos7安装Docker 基于Dockerfile 搭建httpd运行环境
    Centos6.x 安装vnc
    KVM虚拟化技术
    ELK监控系统nginx / mysql慢日志
    ELK初学搭建(elasticsearch)
    (转)Linux 磁盘IO性能测试
    hadoop2.9.2 调整jvm
    (转)shell调试方法
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8776553.html
Copyright © 2011-2022 走看看