zoukankan      html  css  js  c++  java
  • 洛谷P4718 【模板】Pollard-Rho算法

    虽然很久以前就听说过PR算法,但前几天第一次打。

    首先miller rabin判断素数,不在复杂度瓶颈。
    pollard rho倍增环长,复杂度是(O(n^{frac{1}{4}} log n))的。
    然而这样复杂度较高,比较难过加强后的数据。

    可以考虑每次倍增时把乘积存下来,然后在增加环长时一次gcd,这样应该是(O(n^{frac{1}{4}}))

    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long i64;
    typedef unsigned long long u64;
    typedef vector<i64> vi64;
    i64 fast_pow(i64 x,i64 y,i64 z){
        //cerr<<"fp"<<x<<" "<<y<<" "<<z<<endl;
        i64 ret=1;
        for (; y; y>>=1,x=(__int128)x*x%z)
            if (y&1) ret=(__int128)ret*x%z;
        return ret;
    }
    u64 RAND(){
        return ((u64)rand()*rand()+rand());
    }
    const int sp[]={2,3,5,7,11,13,17,19,23,29,31,37,43,47};
    bool is_prime(i64 n){
        //cerr<<"is_prime"<<n<<endl;
        if (n==2) return 1;
        if (~n&1) return 0;
        i64 u=n-1;
        int b=0;
        while (~u&1){
            u>>=1;
            ++b;
        }
        for (int i=0; i<12&&sp[i]<n; ++i){
            i64 now=fast_pow(sp[i],u,n),la=now;
            //cerr<<a<<" "<<u<<" "<<now<<" "<<i<<endl;
            if (now!=1)
            for (int i=1; i<=b; ++i){
                now=(__int128)now*now%n;
                if (now==1){
                    if (la!=n-1) return 0;
                    break;
                }
                la=now;
            }
            //cerr<<"now"<<now<<endl;
            if (now!=1) return 0;
        }
        return 1;
    }
    i64 fix(i64 a,i64 n){
        return a<0?a+n:a;
    }
    i64 gcd(i64 a,i64 b){
        int shift=__builtin_ctzll(a|b);
        b>>=__builtin_ctzll(b);
        while (a){
            a>>=__builtin_ctzll(a);
            if (a<b) swap(a,b);
            a-=b;
        }
        return b<<shift;
    }
    i64 pollard_rho(i64 n,i64 c){
        //cerr<<"pollard_rho"<<n<<" "<<c<<endl;
        i64 i=1,k=2,x=RAND()%(n-1)+1,y=x,g=1;
        while (1){
            ++i;
            x=((__int128)x*x+c)%n;
            //i64 tmp=gcd(fix(x-y,n),n);
            //cerr<<x<<" "<<y<<endl;
            //if (tmp>1) return tmp;
            g=(__int128)fix(x-y,n)*g%n;
            if (i==k){
            	g=gcd(g,n);
            	if (g>1){
            		if (g==n){
            			x=y;
            			while (g==1){
            				x=((__int128)x*x+c)%n;
            				g=gcd(fix(x-y,n),n);
            			}
            		}
            		return g;
            	}
                y=x;
                k<<=1;
            }
        }
    }
    vi64 v;
    void fj(i64 n){
        if (n==1) return;
        if (is_prime(n)){
            //cerr<<"N"<<n<<endl;
            v.push_back(n);
            return;
        }
        i64 p=n;
        while (p>=n){
            p=pollard_rho(n,RAND()%n);
        }
        fj(p);
        fj(n/p);
    }
    typedef vector<pair<i64,int> > vpi64i;
    vpi64i vv;
    int k,p;
    int fp(int x,int y){
        int ret=1;
        for (; y; y>>=1,x=(i64)x*x%p) if (y&1) ret=(i64)ret*x%p;
        return ret;
    }
    int C(int x){
        return ((u64)x*(x+1)>>1)%p;
    }
    int mul(int x,int y){
        return (i64)x*y%p;
    }
    int add(int x,int y){
        return (x+=y)>=p?x-p:x;
    }
    int main(){
        int t;
        cin>>t;
        while (t--){
            i64 n;
            cin>>n;
            //FastDiv fd(p);
            if (n==1){
                cout<<1<<'
    ';
                continue;
            }
            v.clear();
            fj(n);
            sort(v.begin(),v.end());
            (v.back()==n?cout<<"Prime":cout<<v.back())<<'
    ';
        }
    }
    
  • 相关阅读:
    BestCoder6 1002 Goffi and Squary Partition(hdu 4982) 解题报告
    codeforces 31C Schedule 解题报告
    codeforces 462C Appleman and Toastman 解题报告
    codeforces 460C. Present 解题报告
    BestCoder3 1002 BestCoder Sequence(hdu 4908) 解题报告
    BestCoder3 1001 Task schedule(hdu 4907) 解题报告
    poj 1195 Mobile phones 解题报告
    二维树状数组 探索进行中
    codeforces 460B Little Dima and Equation 解题报告
    通过Sql语句控制SQLite数据库增删改查
  • 原文地址:https://www.cnblogs.com/Yuhuger/p/10634343.html
Copyright © 2011-2022 走看看