zoukankan      html  css  js  c++  java
  • 【数学】PollardRho算法

    这个是整数分解PollardRho算法。不是离散对数PollardRho算法,在竞赛里面离散对数一般使用BSGS算法解决,虽然消耗一些空间,但是复杂度稳定。

    快速乘可以替换成其他正确形式的乘法。
    MR可以适当去掉一些,例如只使用2,7,61。

    每次调用PR返回其中一个非1的因子,所以在外面套一层getFactor返回其中一个非平凡因子。

    对速度有要求时应该只对超过线性筛范围的数字进行getFactor。

    不要直接调用PR,对质数调用PR会直接死循环。(MR算法只会把强伪质数误判为质数,不会导致PR算法TLE)

    ll qmul(ll a, ll b, ll mod) {
        return (__int128)a * b % mod;
    }
    
    ll qpow(ll x, ll n, ll mod) {
        if(x >= mod)
            x %= mod;
        ll res = 1;
        while(n) {
            if(n & 1)
                res = qmul(res, x, mod);
            x = qmul(x, x, mod);
            n >>= 1;
        }
        return res;
    }
    
    namespace MillerRabin {
    
        // private
        bool MR(ll n, ll p) {
            for(ll k = n - 1; k; k >>= 1) {
                ll t = qpow(p, k, n);
                if(t != 1 && t != n - 1)
                    return false;
                if((k & 1) == 1 || t == n - 1)
                    // probably true
                    return true;
            }
            // probably true
            return true;
        }
    
        // public
        bool isPrime(ll n) {
            if(n <= 1)
                return false;
            if(n <= 3)
                return true;
            if(!(n & 1))
                return false;
            static int basePrime[5] = {2, 3, 7, 61, 24251};
            for(int i = 1; i <= 5; ++i) {
                if(n == basePrime[i - 1])
                    return true;
                if(!MR(n, basePrime[i - 1]))
                    return false;
            }
            if(n == 46856248255981LL)
                return false;
            // probably true
            return true;
        }
    
    }
    
    using namespace MillerRabin;
    
    namespace PollardRho {
    
        // private
        ll PR(ll n) {
            ll s = 0, t = 0, c = rand() % (n - 1) + 1;
            for(int i = 1;; i <<= 1, s = t) {
                ll p = 1;
                for(int j = 1; j <= i; ++j) {
                    t = (qmul(t, t, n) + c) % n;
                    p = qmul(p, abs(t - s), n);
                    if(p == 0)
                        return n;
                    if(j % 127 == 0) {
                        ll d = __gcd(p, n);
                        if(d > 1)
                            return d;
                    }
                }
                ll d = __gcd(p, n);
                if(d > 1)
                    return d;
            }
        }
    
        // public
        ll getFactor(ll n) {
            if(n <= 3)
                return n;
            if(!(n & 1))
                return 2;
            if(isPrime(n))
                return n;
            ll d = PR(n);
            while(d == n)
                d = PR(n);
            return d;
        }
    
    }
    
    using namespace PollardRho;
    
  • 相关阅读:
    3D集合图元:最小边界框/包围盒(boundingbox)
    vs2012下 error4996
    将自己的类封装为lib的方法
    3D特征:关于HFM和HBB
    C++的Matlab接口
    BigDataMini导论
    vs2012编译boost_1_54_0
    RGB_D_开发征程(使用Kinect)
    **PCD数据获取:Kinect+OpenNI+PCL对接(代码)
    PCL:全程详解 VS2010+PCL配置
  • 原文地址:https://www.cnblogs.com/purinliang/p/13676574.html
Copyright © 2011-2022 走看看