zoukankan      html  css  js  c++  java
  • HDU3864 D_num

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    题目链接:HDU3864

    正解:$Pollard-rho$

    解题报告:

      $Pollard-rho$算法模板题。

      考虑对于一个数$n$,我们有一个$n$以内的数对$(x,y)$,若$gcd(x-y,n)!=1$,那么显然找到了一个$n$的因数$g$,递归往下做下去,分别分解质因子即可。

      这个做法的期望次数会很少,可以想想生日悖论。

      具体做法就是构造一个序列$x_i$,$x_i=x_{i-1}^2+c$,$x_0$、$c$均为$n$以内不为$0$的随机数,我们就这样做下去,$y$就取$2$的次幂,$x$单增,直到找到为止。

      发现有可能如果$x_0$、$c$不好的话可能无解(出现环),需要多随几次,环的判断就是$x$、$y$某次突然相等了。

    //It is made by ljh2000
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    #include <complex>
    #include <bitset>
    using namespace std;
    typedef long long LL;
    typedef long double LB;
    typedef complex<double> C;
    const double pi = acos(-1);
    LL n;
    vector<LL>w;
    
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline LL gcd(LL x,LL y){ if(y==0) return x; return gcd(y,x%y); }
    
    inline LL mul(LL x,LL y,LL mod){
        LL r=0;
        while(y>0) {
            if(y&1) r+=x,r%=mod;
            x+=x; x%=mod;
            y>>=1;
        }
        return r;
    }
    
    inline LL fast_pow(LL x,LL y,LL mod){
        LL r=1;
        while(y>0) {
            if(y&1) r=mul(r,x,mod);
            x=mul(x,x,mod);
            y>>=1;
        }
        return r;
    }
    
    inline int MillerRabin(LL n){
        if(n==1) return 0; if(n==2) return 1; if(!(n&1)) return 0;
        LL aa=n-1,k=0,bb,lin,cc; while(!(aa&1)) aa>>=1,k++; int T=5;
        while(T--) {
            bb=rand()%(n-1)+1; cc=fast_pow(bb,aa,n);
            for(LL i=1;i<=k;i++) {
                lin=mul(cc,cc,n);
                if(lin==1 && cc!=1 && cc!=n-1) return 0;
                cc=lin;
            }
            if(cc!=1) return 0;
        }
        return 1;
    }
    
    inline LL nex(LL x,LL c,LL n){
        return (mul(x,x,n)+c)%n;
    }
    
    inline void pollardrho(LL n){
        while(!(n&1)) n>>=1,w.push_back(2); if(n==1) return ;
        if(MillerRabin(n)) { w.push_back(n); return ; }
        LL x=rand()%(n-1)+1,y=x,c=rand()%(n-1)+1,g;
        for(LL i=1,j=1;;i++) {
            x=nex(x,c,n);
            g=gcd(abs(x-y),n);
            if(x==y) x=rand()%(n-1)+1,y=x,c=rand()%(n-1)+1,i=0,j=1;
            if(g>1 && g<n) break;
            if(i==j) j<<=1,y=x;
        }
        pollardrho(g); pollardrho(n/g);
    }
     
    inline void work(){
        srand(time(NULL));
        while(scanf("%lld",&n)!=EOF) {
            if(n==1){ cout<<"is not a D_num"<<endl; continue; }
            w.clear();
            pollardrho(n);
            int t=w.size();
            if(t!=2&&t!=3){ cout<<"is not a D_num"<<endl; continue; }  
    
            sort(w.begin(),w.end());  
    
            if(t==2) {  
                if(w[0]!=w[1]) cout<<w[0]<<" "<<w[1]<<" "<<n<<endl;  
                else cout<<"is not a D_num"<<endl;  
            }  
            else {  
                if(w[0]==w[1] && w[1]==w[2]) cout<<w[0]<<" "<<w[0]*w[0]<<" "<<n<<endl;  
                else cout<<"is not a D_num"<<endl;  
            }  
        }
    }
     
    int main()
    {   
    	work();
        return 0;
    }
    //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
    

      

  • 相关阅读:
    sqlalchemy的orm的高级用法,分组,排序,聚合等方法
    flask的SQLAlchemy,连接数据库的增删改查操作
    wtforms的form表单的高级用法
    初始wtforms表单,以及简单使用
    命令启动flask以及自定义命令
    MySQL5.5安装教程
    Java设计模式-策略模式实际应用场景
    Java设计模式-策略模式详解
    Oracle数据库之FORALL与BULK COLLECT语句
    代理模式详解(静态代理和动态代理的区别以及联系)
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6609719.html
Copyright © 2011-2022 走看看