• 整数分解 专题


    pollard_rho讲解

    大神orz

    poj 1811Prime Test http://poj.org/problem?id=1811

    坑点:re了好多发,一直以为dfs次数太多,检查了很多次都不觉得会爆,数组也开得足够大,最后一种可能就是除0了.。。。。pollard_rho中有一步(y-x)的操作可能出现<=0的情况。。。。这是个pollard_rho的基本题,可以用来做模板

    /**************************************************************
        Problem:poj 1811
        User: youmi
        Language: C++
        Result: Accepted
        Time:704MS
        Memory:708K
    ****************************************************************/
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#include<bits/stdc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <stack>
    #include <set>
    #include <sstream>
    #include <cmath>
    #include <ctime>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #define zeros(a) memset(a,0,sizeof(a))
    #define ones(a) memset(a,-1,sizeof(a))
    #define sc(a) scanf("%d",&a)
    #define sc2(a,b) scanf("%d%d",&a,&b)
    #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scs(a) scanf("%s",a)
    #define sclld(a) scanf("%I64d",&a)
    #define pt(a) printf("%d
    ",a)
    #define ptlld(a) printf("%I64d
    ",a)
    #define rep0(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define rep_1(i,n) for(int i=n;i>=1;i--)
    #define rep_0(i,n) for(int i=n-1;i>=0;i--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define lson (step<<1)
    #define rson (lson+1)
    #define esp 1e-6
    #define oo 0xffffffffffffff
    #define TEST cout<<"*************************"<<endl
    
    using namespace std;
    typedef long long ll;
    ll ans;
    const int maxn=100000;
    ll fact[maxn];
    const int Times=10;
    const int C=201;
    int cnt=0;
    ll gcd(ll a,ll b)
    {
        return b==0?a:gcd(b,a%b);
    }
    ll q_mul(ll a,ll b,ll mod)
    {
        ll res=0;
        a%=mod;
        while(b)
        {
            if(b&1)
                res=(res+a)%mod;
            b>>=1;
            a=(a<<1)%mod;
        }
        return res;
    }
    ll q_pow(ll a,ll b,ll mod)
    {
        ll res=1;
        a%=mod;
        while(b)
        {
            if(b&1)
                res=q_mul(res,a,mod);
            b>>=1;
            a=q_mul(a,a,mod);
        }
        return res;
    }
    bool miller_rabin(ll n)
    {
        if(n<2)
            return false;
        if(n==2)
            return true;
        if(!(n&1))
            return false;
        ll u=n-1;
        int tot=0;
        while(!(u&1))
        {
            u>>=1;tot++;
        }
        rep1(i,Times)
        {
            ll x=rand()%(n-2)+2;
            if(x==n)
                continue;
            x=q_pow(x,u,n);
            ll pre=x;
            rep0(j,tot)
            {
                x=q_mul(x,x,n);
                if(x==1&&pre!=1&&pre!=n-1)
                    return false;
                pre=x;
            }
            if(x!=1)
                return false;
        }
        return true;
    }
    ll pollard_rho(ll n,ll c)
    {
        ll x,y,d,i=1,k=2;
        x=rand()%(n-1)+1;
        y=x;
        while(1)
        {
            i++;
            x=(q_mul(x,x,n)+c)%n;
            d=gcd(n,(y-x+n)%n);//注意!!!!!!!!!
            if(d>1&&d<n)
                return d;
            if(y==x)
                return n;
            if(i==k)
            {
                y=x;
                k<<=1;
            }
        }
    }
    void Find(ll n,int k)
    {
        if(n==1)
            return ;
        if(miller_rabin(n))
        {
            fact[++cnt]=n;
            if(n<ans)
                ans=n;
            return;
        }
        ll p=n;
        while(p>=n)
            p=pollard_rho(p,k--);
        Find(p,k);
        Find(n/p,k);
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T_T;
        scanf("%d",&T_T);
        ll n;
        for(int kase=1;kase<=T_T;kase++)
        {
            scanf("%lld",&n);
            if(miller_rabin(n))
                printf("Prime
    ");
            else
            {
                cnt=0;
                ans=n;
                Find(n,C);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }

    poj 2429 GCD & LCM Inverse  http://poj.org/problem?id=2429 

    思路:now=lcm/gcd 的因子是a,b所不同的,所以只需对now进行整数分解(因为Now比较大,所以用pollard_rho),分解出来的因子,相同因子一定分在一起,要不然gcd应该更大(至少应该乘这个相同因子)所以,又因为11个素数相乘的大小就差不多能达到10^18,所以只需对用dfs深搜一下(2^11层),或者把2^tot-1个状态一一列举就行了。。。dfs的速度更快

    /**************************************************************
        Problem:poj 2429
        User: youmi
        Language: C++
        Result: Accepted
        Time:79MS
        Memory:148K
    ****************************************************************/
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    //#include<bits/stdc++.h>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <stack>
    #include <set>
    #include <ctime>
    #include <sstream>
    #include <cmath>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #define zeros(a) memset(a,0,sizeof(a))
    #define ones(a) memset(a,-1,sizeof(a))
    #define sc(a) scanf("%d",&a)
    #define sc2(a,b) scanf("%d%d",&a,&b)
    #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
    #define scs(a) scanf("%s",a)
    #define sclld(a) scanf("%I64d",&a)
    #define pt(a) printf("%d
    ",a)
    #define ptlld(a) printf("%I64d
    ",a)
    #define rep0(i,n) for(int i=0;i<n;i++)
    #define rep1(i,n) for(int i=1;i<=n;i++)
    #define rep_1(i,n) for(int i=n;i>=1;i--)
    #define rep_0(i,n) for(int i=n-1;i>=0;i--)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define lson (step<<1)
    #define rson (lson+1)
    #define esp 1e-6
    #define oo 0x3fffffff
    #define TEST cout<<"*************************"<<endl
    
    using namespace std;
    typedef unsigned long long ll;
    const int maxn=100000;
    ll fact[maxn];
    ll a[maxn];
    const int C=201;
    const int Times=5;
    ll gcd(ll a,ll b)
    {
        return b==0?a:gcd(b,a%b);
    }
    ll q_mul(ll a,ll b,ll mod)
    {
        ll res=0;
        while(b)
        {
            if(b&1)
                res=(res+a)%mod;
            b>>=1;
            a=(a<<1)%mod;
        }
        return res;
    }
    ll q_pow(ll a,ll b,ll mod)
    {
        ll res=1;
        while(b)
        {
            if(b&1)
                res=q_mul(res,a,mod);
            b>>=1;
            a=q_mul(a,a,mod);
        }
        return res;
    }
    bool miller_rabbin(ll n)
    {
        if(n<2)
            return false;
        if(n==2)
            return true;
        if(!(n&1))
            return false;
        ll u=n-1;
        int tot=0;
        while(!(u&1))
        {
            u>>=1;tot++;
        }
        rep0(i,Times)
        {
                ll x=rand()%(n-2)+2;
                x=q_pow(x,u,n);
                ll pre=x;
                for(int j=0;j<tot;j++)
                {
                    x=q_mul(x,x,n);
                    if(x==1&&pre!=1&&pre!=n-1)
                        return false;
                    pre=x;
                }
                if(x!=1)
                    return false;
        }
        return true;
    }
    ll pollard_rho(ll n,ll c)
    {
        ll x,y,d,i=1,k=2;
        x=rand()%(n-1)+1;
        y=x;
        while(1)
        {
            i++;
            x=(q_mul(x,x,n)+c)%n;
            d=gcd(n,(y-x+n)%n);
            if(d>1&&d<n)
                return d;
            if(x==y)
                return n;
            if(i==k)
            {
                y=x;
                k<<=1;
            }
        }
    }
    int cnt;
    void Find(ll n,int k)
    {
        if(n==1)
            return ;
        if(miller_rabbin(n))
        {
            fact[++cnt]=n;
            return ;
        }
        ll p=n;
        while(p>=n)
            p=pollard_rho(n,k--);
        Find(p,k);
        Find(n/p,k);
    }
    ll ans,n,m,maxa;
    int all;
    /**< 148K    94MS 这是另一种思路
    void solve()
    {
        ll x,y;
        pair<ll,ll>ans=make_pair(1,n/m);
        ll mini=ans.first+ans.second;
        ll bit=(1ll<<all)-1;
        for(int i=1;i<=bit;i++)
        {
            x=1;
            for(int j=1;j<=all;j++)
            {
                if(i&(1ll<<(j-1)))
                    x*=a[j];
            }
            y=maxa/x;
            if(x<y&&x+y<mini)
            {
                mini=x+y;
                ans.first=x;
                ans.second=y;
                //printf("x->%llu y->%llu mini->%llu
    ",x,y,mini);
            }
        }
        printf("%llu %llu
    ",ans.first*m,m*ans.second);
    }
     */
    void dfs(ll cur,int temp)
    {
        if(temp>all)
            return;
        if(ans+maxa/ans>cur*a[temp]+maxa/(cur*a[temp]))
        {
            ans=cur*a[temp];
        }
        dfs(cur*a[temp],temp+1);
        dfs(cur,temp+1);
    }
    bool cmp(ll c,ll b)
    {
        return c<b;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%llu%llu",&m,&n))
        {
            if(n==m)
            {
                printf("%llu %llu
    ",n,m);
                continue;
            }
            maxa=n/m;
            cnt=0;
            Find(maxa,C);
            sort(fact+1,fact+cnt,cmp);
            all=1;
            a[all]=fact[1];
            for(int i=2;i<=cnt;i++)
            {
                if(fact[i]!=fact[i-1])
                {
                    a[++all]=fact[i];
                }
                else
                    a[all]*=fact[i];
            }
            ans=a[1];
            dfs(a[1],2);
            ll ans2=maxa/ans;
            ll temp;
            if(ans>ans2)
            {
                temp=ans;
                ans=ans2;
                ans2=temp;
            }
            printf("%llu %llu
    ",ans*m,m*ans2);
        }
        return 0;
    }
    (*  ̄3)(ε ̄ *)
    不为失败找借口,只为成功找方法
  • 相关阅读:
    Windows netsh命令的使用
    源码安装 qemu-2.0.0 及其依赖 glib-2.12.12
    .ko文件
    Suse环境下编译linux-2.6.24内核
    cut
    POJ3648 Wedding
    [Hnoi2010]Planar
    [中山市选2011]杀人游戏
    BZOJ3033 太鼓达人
    POJ1041 John's trip
  • 原文地址:https://www.cnblogs.com/youmi/p/4921880.html
Copyright © 2020-2023  润新知