pollard_rho例题

时间:2020-03-26
本文章向大家介绍pollard_rho例题,主要包括pollard_rho例题使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

\(pollard\_rho\) 例题

\(POJ 1811\)

题意:判断一个数是不是素数,如果是素数,输出 \(Prime\) 否则,输出最小的素因子。

题解:使用 \(Miller\_Rabin\) 法则筛选素数,之后使用 \(pollard\_rho\) 进行因子分解,找到最小值。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAXN = 501;
const int TestCase = 10;
int cnt;
ll N;
ll minn,mina,minb;
ll prime[MAXN];
ll fac[MAXN];
ll num[MAXN];
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll random(ll n){
    return (ll)((double)rand()/RAND_MAX*n+0.5);
}
ll multi(ll a,ll b,ll m){
    ll ret=0;
    while(b>0){
        if(b&1)ret=(ret+a)%m;
        b>>=1;
        a=(a<<1)%m;
    }
    return ret;
}
ll pow(ll a,ll b,ll m){
    ll ans=1;
    a%=m;
    while(b){
        if(b&1)ans=multi(ans,a,m);
        b>>=1;
        a=multi(a,a,m);
    }
    return ans;
}
bool Witness(ll a,ll n){
    ll m=n-1;
    int j=0;
    while(!(m&1)){
        ++j;m>>=1;
    }
    ll x=pow(a,m,n);
    if(x==1||x==n-1)return false;
    while(j--){
        x=x*x%n;
        if(x==n-1)return false;
    }
    return true;
}
bool miller_rabin(ll n){
    if(n<2)return false;
    if(n==2)return true;
    if(!(n&1))return false;
    for(int i=1;i<=TestCase;++i){
        ll a=random(n-2)+1;
        if(Witness(a,n))return false;
    }
    return true;
}
ll pollard_rho(ll n,int c){
    ll x,y,d,i=1,k=2;
    x=random(n-1)+1;
    y=x;
    while(true){
        ++i;
        x=(multi(x,x,n)+c)%n;
        d=gcd(y-x,n);
        if(1<d&&d<n)return d;
        if(x==y)return n;
        if(i==k){
            y=x;
            k<<=1;
        }
    }
}
void find(ll n,int k){
    if(n==1)return;
    if(miller_rabin(n)){
//        prime[++cnt]=n;
        minn=min(minn,n);
        return;
    }
    ll p=n;
    while(p>=n)
        p=pollard_rho(p,--k);
    find(p,k);
    find(n/p,k);
}
int main(){
    ll T;
    cin>>T;
    while(T--){
        ll N;
        cin>>N;
        if(miller_rabin(N))cout<<"Prime"<<endl;
        else {
            minn=N;
            find(N,107);
            cout<<minn<<endl;
        }
    }
    return 0;
}

\(POJ 2429\)

题意:已知 \(gcd(a,b)\)\(lcm(a,b)\) 求解 \(a\) , \(b\) 使得 \(a+b\) 最小

题解:使用 \(pollard\_rho\) 进行质数分解,之后使用 \(dfs\) 搜索即可。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MAXN = 501;
const int TestCase = 10;
int cnt;
ll N;
ll prime[MAXN];
ll fac[MAXN];
ll num[MAXN];
ll gcd(ll a,ll b){
    return b==0?a:gcd(b,a%b);
}
ll random(ll n){
    return (ll)((double)rand()/RAND_MAX*n+0.5);
}
ll multi(ll a,ll b,ll m){
    ll ret=0;
    while(b>0){
        if(b&1)ret=(ret+a)%m;
        b>>=1;
        a=(a<<1)%m;
    }
    return ret;
}
ll pow(ll a,ll b,ll m){
    ll ans=1;
    a%=m;
    while(b){
        if(b&1)ans=multi(ans,a,m);
        b>>=1;
        a=multi(a,a,m);
    }
    return ans;
}
bool Witness(ll a,ll n){
    ll m=n-1;
    int j=0;
    while(!(m&1)){
        ++j;m>>=1;
    }
    ll x=pow(a,m,n);
    if(x==1||x==n-1)return false;
    while(j--){
        x=x*x%n;
        if(x==n-1)return false;
    }
    return true;
}
bool miller_rabin(ll n){
    if(n<2)return false;
    if(n==2)return true;
    if(!(n&1))return false;
    for(int i=1;i<=TestCase;++i){
        ll a=random(n-2)+1;
        if(Witness(a,n))return false;
    }
    return true;
}
ll pollard_rho(ll n,int c){
    ll x,y,d,i=1,k=2;
    x=random(n-1)+1;
    y=x;
    while(true){
        ++i;
        x=(multi(x,x,n)+c)%n;
        d=gcd(y-x,n);
        if(1<d&&d<n)return d;
        if(x==y)return n;
        if(i==k){
            y=x;
            k<<=1;
        }
    }
}
void find(ll n,int k){
    if(n==1)return;
    if(miller_rabin(n)){
        prime[++cnt]=n;
        return;
    }
    ll p=n;
    while(p>=n)
        p=pollard_rho(p,--k);
    find(p,k);
    find(n/p,k);
}
ll minn,mina,minb;
int len=0;
void dfs(int id,ll tmp){
    if(id==len+1){
        if(N/tmp+tmp<minn){
            mina=tmp;
            minb=N/tmp;
            minn=mina+minb;

        }
        return;
    }
    dfs(id+1,tmp);
    tmp*=fac[id];
    if(tmp>=minn)return;
    dfs(id+1,tmp);
}
void slove(ll n,ll x){
    cnt=0;
    find(n,107);
    sort(prime+1,prime+cnt+1);
    len=0;
    fac[len]=prime[1];
    num[len]=1;
    for(int i=2;i<=cnt;++i){
        if(fac[len]==prime[i]){
            ++num[len];
        }
        else{
            fac[++len]=prime[i];
            num[len]=1;
        }
    }
    for(int i=0;i<=len;++i){
        ll tmp=1;
        for(int j=0;j<num[i];++j){
            tmp*=fac[i];
        }
        fac[i]=tmp;
    }
//    for(int i=0;i<=len;++i)
//        cout<<num[i]<<" "<<fac[i]<<endl;
}
int main(){
    ll x,y;
    while(cin>>x>>y){
        if(x==y)cout<<x<<" "<<y<<endl;
        else {
            N=y/x;
            slove(N,x);
            minn=N+1;
            mina=1;minb=N;
            dfs(0,1);
            cout<<min(mina,minb)*x<<" "<<(mina+minb-min(mina,minb))*x<<endl;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/VagrantAC/p/12573017.html