zoukankan      html  css  js  c++  java
  • 【模板】数论

    1 最大公约数 (gcd)

    int gcd(int a, int b) {return b ? gcd(b, a % b) : a;}

    2 快速幂 (递归版本)

    ll PowerMod(ll a, ll n, ll m = mod) {
        if (!n || a == 1) return 1ll;
        ll s = PowerMod(a, n >> 1, m);
        s = s * s % m;
        return n & 1 ? s * a % m : s;
    }

    3 快速幂 (非递归版本) 

    ll PowerMod(ll a, int n, ll c = 1) 
    {
        for (; n; n >>= 1, a = a * a % mod)
        if (n & 1) 
        c = c * a % mod;
        return c;
    }

    4 扩展 Euclid 算法 (exgcd)

    ll exgcd(ll a, ll b, ll &x, ll &y) 
    {
         if (b) 
       {
        ll d = exgcd(b, a % b, y, x); 
        return y -= a / b * x, d;
       }
        else return x = 1, y = 0, a;
    }

    5 基本预处理 

    // factorials, fact-inverses, unbounded
    void init() {
        int i;
        for (*fact = i = 1; i < N; ++i) 
            fact[i] = (ll)fact[i - 1] * i % mod;
        --i;
            finv[i] = PowerMod(fact[i], mod - 2);
        for (; i; --i) 
            finv[i - 1] = (ll)finv[i] * i % mod;
    }
    
    // factorials, fact-inverses, bounded
    void init(int n) {
        int i;
        for (*fact = i = 1; i <= n; ++i)
            fact[i] = (ll)fact[i - 1] * i % mod;
        finv[n] = PowerMod(fact[n], mod - 2);
        for (i = n; i; --i) 
            finv[i - 1] = (ll)finv[i] * i % mod;
    }
    
    // inverses, factorials, fact-inverses, unbounded
    void init() {
        int i;
        for (inv[1] = 1, i = 2; i < N; ++i)
            inv[i] = ll(mod - mod / i) * inv[mod % i] % mod;
        for (*finv = *fact = i = 1; i < N; ++i)
            fact[i] = (ll)fact[i - 1] * i % mod, finv[i] = (ll)finv[i - 1] * inv[i] % mod;
    }
    
    // inverses, factorials, fact-inverses, bounded
    void init(int n) {
        int i;
        for (inv[1] = 1, i = 2; i <= n; ++i) 
            inv[i] = ll(mod - mod / i) * inv[mod % i] % mod;
        for (*finv = *fact = i = 1; i <= n; ++i) 
            fact[i] = (ll)fact[i - 1] * i % mod, 
            finv[i] = (ll)finv[i - 1] * inv[i] % mod;
    }

    6 线性筛素数 (筛最小素因子)

    int pn = 0, c[N], p[78540];
    
    void sieve(int n) {
        int i, j, v;
        memset(c, -1, sizeof c);
        for (i = 2; i <= n; ++i) {
        if (!~c[i]) p[pn] = i, c[i] = pn++;
        for (j = 0; (v = i * p[j]) <= n && j <= c[i]; ++j) 
            c[v] = j;
        }
    }

    7 Miller-Rabin 素数测试

    // No pseudoprime below 2^64 to base 2, 3, 5, 7, 11, 13, 82, 373.
    const int test[8] = {2, 3, 5, 7, 11, 13, 82, 373};
    bool Miller_Rabin(ll n) {
        if (n < MAX) return !c[n] && n > 1;
        int c, i, j; ll s = n - 1, u, v;
        for (c = 0; !(s & 1); ++c, s >>= 1);
        for (i = 0; i < 8; ++i) {
           if (!(n % test[i])) return false;
           u = PowerMod(test[i], s, n);
           for (j = 0; j < c; ++j, u = v)
              if (v = MulMod(u, u, n), u != 1 && u != n - 1 && v == 1) return false;
              if (u != 1) return false;
        }
        return true;
    }

    8 分解质因数

    // version 1
    inline void push(ll prime, int alpha)
     {pr[cnt] = prime, al[cnt++] = alpha;}
    
    // version 2
    inline void push(ll prime, int alpha) {
        map::iterator it = result.find(prime);
        it == result.end() ? (void)result.emplace(prime, alpha) : (void)(it->second += alpha);
    }
    
    void factor(ll n) {
        int i, j; cnt = 0; // result.clear();
        for (i = 0; n > 1; ) {
           if (n >= N) {
           for (; (ll)p[i] * p[i] <= n && n % p[i]; ++i);
            if (n % p[i]) return push(n, 1);
            } else i = c[n];
            for (j = 0; !(n % p[i]); n /= p[i], ++j); 
                    push(p[i], j);
        }
    }

    9 线性筛 Euler φ 函数

    void sieve(int n) {
        int i, j, v; phi[1] = 1;
        memset(c, -1, sizeof c);
        for (i = 2; i <= n; ++i) {
        if (!~c[i]) 
            p[pn] = i, c[i] = pn++, phi[i] = i - 1;
        for (j = 0; (v = i * p[j]) <= n && j < c[i]; ++j) 
            c[v] = j, phi[v] = phi[i] * (p[j] - 1);
        if (v <= n) 
            c[v] = j, phi[v] = phi[i] * p[j];
        }
    }

    10 线性筛 Möbius μ 函数 

    void sieve(int n) {
        int i, j, v; mu[1] = 1;
        memset(c, -1, sizeof c);
        for (i = 2; i <= n; ++i) {
        if (!~c[i]) 
            p[pn] = i, c[i] = pn++, mu[i] = -1;
        for (j = 0; (v = i * p[j]) <= n && j < c[i]; ++j) 
            c[v] = j, mu[v] = -mu[i];
        if (v <= n) c[v] = j;
        }
    }

    11 遍历 ⌊n / i⌋ 的所有可能值 (旧版整除分块)

    #define next(n, i) (n / (n / i + 1))
    for(i = n; i >= 1; i = j){
        j = next(n, i);
        // do something
    }
    
    #define _next(n, i) (n / (n / (i + 1)))
    for(i = 0; i < n; i = j){
        j = _next(n, i);
        // do something
    }
    
    // 0 1 100 1 2 50 2 3 33 3 4 25 4 5 20 5 6 16 16 6 7 14 7 8 12 8 9 11 9 10 10 10 11 9 11 12 8 12 13 7 14 15 6 16 17 5 20 21 4 25 26 3 33 34 2 50 51 1 100 101 0 ?

    12 新版整除分块

    // int32 ver.
    int n, cnt, srn;
    int v[G];
    
    inline int ID(int x) {return x <= srn ? x : cnt + 1 - n / x;}
    
    {
        int i;
        srn = sqrt(n), cnt = srn * 2 - (srn * (srn + 1) > n);
        for (i = 1; i <= srn; ++i)
            v[i] = i, v[cnt - i + 1] = n / i;
    }
    
    // int64 ver.
    ll n, v[G];
    int cnt, srn;
    
    inline int ID(ll x) {return x <= srn ? x : cnt + 1 - n / x;}
    
    {
        int i;
        srn = sqrt(n), cnt = srn * 2 - (srn * (srn + 1) > n);
        for (i = 1; i <= srn; ++i) 
            v[i] = i, v[cnt - i + 1] = n / i;
    }

    13 杜氏求和法 / 杜教筛

    void Dsum() {
        int i, j, k, l, n, sq, _;
        for (i = 1; i <= cnt && v[i] < N; ++i) 
            Mu[i] = smu[v[i]], Phi[i] = sphi[v[i]];
        for (; i <= cnt; ++i) {
            int &m = Mu[i];
                ll &p = Phi[i];
            n = v[i], sq = sqrt(n), m = 1, p = n * (n + 1ll) / 2, l = n / (sq + 1);
            for (j = sq; j; --j) {
            _ = (k = n / j) - l, m -= _ * smu[j], p -= _ * sphi[j], l = k;
            if (j != 1 && k > sq) m -= Mu[_ = ID(k)], p -= Phi[_];
            }
        }
    }

    14大小步离散对数

    int Boy_Step_Girl_Step(){
        mii :: iterator it;
        ll boy = 1, girl = 1, i, t;
        for(i = 0; i < B; i++){
            m.insert(pr((int)boy, i)); // if there exists in map, then ignore it
            (boy *= a) %= p;
        }
        for(i = 0; i * B < p; i++){
            t = b * inv(girl) % p;
            it = m.find((int)t);
            if(it != m.end())
                return i * B + it->second;
            (girl *= boy) %= p;
        }
        return -1;
    } 
    
    // input p and then B = (int)sqrt(p - 1);
    // inv(x) is the multiplicative inverse of x in Z[p].
    // mii: map <int, int> and m is a variable of which.

    15 Pollard-Rho 素因数分解

    ll Pollard_Rho(ll n, int c) {
        ll i = 1, k = 2, x = rand() % (n - 1) + 1, y = x, p;
        for (; k <= 131072; ) 
           {
        x = (MulMod(x, x, n) + c) % n;
        p = gcd<ll>((ull)(y - x + n) % n, n);
        if (p != 1 && p != n) return p;
        if (++i == k) y = x, k <<= 1;
        }
        return 0;
    }
    
    inline void push(ll prime, int alpha) {
        map::iterator it = result.find(prime);
        it == result.end() ? (void)result.insert(pr(prime, alpha)) : (void)(it->second += alpha);
    }
    
    void factor(ll n) {
        int i, j, k; ll p;
        for (i = 0; n != 1; )
        if (n >= MAX) {
        if (Miller_Rabin(n)) {push(n, 1); return;}
        for (k = 97; !(p = Pollard_Rho(n, k)); --k);
        factor(p); n /= p;
        }
            else {
        i = (c[n] ? c[n] : n);
        for (j = 0; !(n % i); n /= i, ++j);
        push(i, j);
        }
    }
  • 相关阅读:
    了解 Spring Data JPA
    Spring MVC 方法注解拦截器
    Spring MVC拦截器+注解方式实现防止表单重复提交
    java中return语句的用法总结
    equal方法在String类与Object类中的区别
    instanceof用法
    EL 简介及用法
    JAVA 四大域对象总结
    JSP基本语法
    Servlet请求转发 RequestDispatcher接口知识点
  • 原文地址:https://www.cnblogs.com/lau1997/p/12665688.html
Copyright © 2011-2022 走看看