zoukankan      html  css  js  c++  java
  • Pollard-Rho

    Solution

    用于拆解较大数的质因子。

    前置知识:Miller Rabin

    涉及到的思想:

    • 利用 (gcd(x,y)) 来寻找 (x) 的因数。

    • 组合随机采样的优秀命中率。

    • (gcd(xcdot z,y)=gcd(gcd(x,y) imes gcd(z,y),y)),因此可以调整步长来判断当前是否找到了因数,减少 (gcd) 的调用次数。

    安利一篇博文,这里面讲得挺详细的,就是有些地方……可能需要你自己理解他真正的意思。


    三道板子题

    【模板】Pollard-Rho算法

    SP4941 FACT1 - Integer Factorization (20 digits)

    「数学」约数个数和

    确实算是板题,毕竟这个东西就是把数字质因子拆分。

    其中第三道题转化完以后就是个 前缀和 的模板。


    Code

    下面是封装好的,可以直接调用,返回质因数拆分的结果。

    测试了 (114514,1919810) 这两个数的拆分。

    namespace Pollard_Rho
    {
        inline LL les(LL x,LL y){return x>y?x-y:y-x;}
        inline LL Gcd(LL x,LL y){return !y?x:Gcd(y,x%y);}
        inline LL prpr(LL x,LL y,LL p){LL s=(long double)x/p*y+1e-8;s=(ULL)(x*y)-(ULL)(s*p);if(s>=p)s-=p;return s<0?s+p:s;}
        inline LL ksm(LL x,LL y,LL p){LL ans=1;for(;y;y>>=1){if(y&1)ans=prpr(ans,x,p);x=prpr(x,x,p);}return ans;}
    
        bool pri[20];
        vector<int>prime;
        inline void init()
        {
            for(int i=2;i<20;i++){if(!pri[i])prime.push_back(i);for(auto j:prime){int now=i*j;if(now>=20)break;pri[now]=true;if(i%j==0)break;}}
            pri[1]=true;srand(time(0));return;
        }
        inline bool Miller_Rabin(LL n,int a)
        {
            LL t=n-1,lst;int k=0;for(;!(t&1);t>>=1)k++;lst=t=ksm(a,t,n);
            for(int i=1;i<=k;i++){t=prpr(t,t,n);if(t==1&&lst!=1&&lst!=n-1)return false;lst=t;}return lst==1;
        }
        inline bool ifprime(LL n){if(n<20)return !pri[n];if(n%6!=1&&n%6!=5)return false;for(auto j:prime)if(!Miller_Rabin(n,j))return false;return true;}
    
        inline LL f(LL x,int c,LL p){LL nows=prpr(x,x,p)+c;if(nows>=p)nows-=p;return nows;}
        inline LL Ame(LL n)
        {
            LL s,t,c;s=t=0;c=rand()%(n-1)+1;
            for(int ed=1;;ed<<=1)
            {
                LL pro=1;s=t;for(int i=1;i<=ed;i++){t=f(t,c,n),pro=prpr(pro,les(t,s),n);if(i%127==0){LL ans=Gcd(n,pro);if(ans>1)return ans;}}
                LL ans=Gcd(n,pro);if(ans>1)return ans;
            }
            return n;
        }
        vector<pair<LL,int> >getpm;
        inline void Gura(LL n,int cutt)
        {
            if(n==1)return;if(ifprime(n)){getpm.push_back(make_pair(n,cutt));return;}
            LL p=n;for(;p==n;p=Ame(n));int c=0;for(;n%p==0;n/=p)c++;Gura(n,cutt);Gura(p,cutt*c);return;
        }
        inline vector<pair<LL,int> > work(LL n)
        {
            getpm.clear();Gura(n,1);sort(getpm.begin(),getpm.end());vector<pair<LL,int> >ans;ans.clear();
            for(vector<pair<LL,int> >::iterator i=getpm.begin(),j;i!=getpm.end();i=j)
            {
                int sum=0;for(j=i;j!=getpm.end()&&j->first==i->first;j++)sum+=j->second;
                ans.push_back(make_pair(i->first,sum));
            }
            return ans;
        }
    }
    int main()
    {
        using namespace Pollard_Rho;init();
        vector<pair<LL,int> >a=work(114514);for(vector<pair<LL,int> >::iterator i=a.begin();i!=a.end();i++)printf("%lld^%d ",i->first,i->second);puts("");
        vector<pair<LL,int> >b=work(1919810);for(vector<pair<LL,int> >::iterator i=b.begin();i!=b.end();i++)printf("%lld^%d ",i->first,i->second);puts("");
        return 0;
    }
    
    $$ exttt{Dirty Deeds Done Dirt Cheap}$$
  • 相关阅读:
    union 和 union all的区别
    JDBC中PreparedStatement相比Statement的好处
    25个经典的Spring面试问答
    MySQL 事务
    漫谈Linux下的音频问题(转)
    监控 Linux 性能的 18 个命令行工具(转)
    在终端中用默认程序打开文件(转)
    【转】使程序在Linux下后台运行 (关掉终端继续让程序运行的方法)
    Getting Started with Amazon EC2 (1 year free AWS VPS web hosting)
    压缩解压命令小结
  • 原文地址:https://www.cnblogs.com/zjjws/p/14693151.html
Copyright © 2011-2022 走看看