• NOIp 基础数论知识点总结


    推荐阅读 NOIp 数学知识点总结: https://www.cnblogs.com/greyqz/p/maths.html


    Basic

    常用素数表:https://www.cnblogs.com/greyqz/p/9845627.html

    快速幂

    int qpow(int x, int y) {
        int res = 1;
        for (; y; x = (ll)x * x % mod, y >>= 1)
            if (y & 1) res = (ll)res * x % mod;
        return res;
    }
    

    矩阵快速幂:

    struct matrix {
        ll m[100][100];
        matrix operator * (matrix &a) {
            matrix b;
            for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++) {
                    b.m[i][j] = 0;
                    for (int k = 0; k < n; k++)
                        b.m[i][j] = (b.m[i][j] + m[i][k] * a.m[k][j]) \% mod;
                }
            return b;
        }
    } s;
    
    matrix mpow(matrix a, ll k) {
        if (k == 1) return a;
        a = mpow(a, k / 2);
        if (k \% 2) return (a * a) * s;
        else return a * a;
    }
    
    matrix a = mpow(s, p);
    

    乘法逆元

    众所周知, 在模意义下没有标准的除法. 为了表示乘法的逆运算, 我们定义:

    ({ m mod} p) 意义下, (x)乘法逆元记为 (x^{-1}), 即 (xcdot x^{-1}equiv 1pmod p).

    由此我们得到 (displaystyle frac{x}{y}equiv xcdot y^{-1}pmod p).

    费马小定理:对于任意素数 (p), 有 (a^{p-1}equiv 1pmod p).

    对费马小定理变形, 得 (acdot a^{p-2}equiv 1pmod p).

    所以 (a^{p-2}) 即为 (a) 的乘法逆元. 对于非素数 (p), 不一定有乘法逆元.

    由此, 使用快速幂求解乘法逆元:

    inline int qpow(int n, int m, int mod) {
        ll tot = 1;
        for (ll k = n; m; k = k * k % mod, m >>= 1)
        	if (m & 1) tot = tot * k % mod;
        return tot;
    }
    
    inline int inv(int x, int mod) {
        return qpow(x, mod - 2);
    }
    

    拓展欧几里得算法用于在线性时间里求解关于 (x,y) 的方程 (ax+by=gcd(a,b)) 的一组整数解.

    (b) 为素数时, (gcd(a,b)=1), 此时有 (axequiv 1pmod b). 从而使用拓展欧几里得算法求解乘法逆元:

    void exgcd(const int a, const int b, int &g, int &x, int &y) {
        if (!b) g = a, x = 1, y = 0;
        else exgcd(b, a % b, g, y, x), y -= x * (a / b);
    }
    
    inline int inv(const int num) {
        int g, x, y;
        exgcd(num, MOD, g, x, y);
        return ((x % MOD) + MOD) % MOD;
    }
    

    以上时间复杂度均为 (O(log a)).

    整除

    最大公约数

    辗转相除法(欧几里得算法):

    int gcd(int x, int y) {
    	return !y ? x : gcd(y, x % y);
    }
    

    大整数意义下的快速更相减损术:

    bint kgcd(bint a, bint b) {
    	if (b == 0) return b;
    	if (a < b) return kgcd(b, a);
    	if (!(a&1) && !(b&1)) return kgcd(a>>1, b>>1) << 1;
    	else if (!(b&1)) return kgcd(a, b>>1);
    	else if (!(a&1)) return kgcd(a>>1, b);
    	else return kgcd(b, a-b);
    }
    

    最小公倍数:( ext{lcm}( a, b ) = a div gcd ( a, b ) imes b). (先除后乘防爆 int. )

    线性筛法

    素数分布定理:对于不大于 (n) 的自然数集合, 素数个数 (pi(x)simdisplaystylefrac{n}{ln{n}}).

    Euler 筛法(一种最常见的线性筛法):

    基本思想:每个数只被最小的质因子筛一次, 即对于 (a) 是质数, (b) 的最小质因子不小于 (a) 的整数对 (a, b), 标记 (ab) 为合数实现:先枚举 (b), 再枚举 (a), 枚举到 (a|b) 时结束.

    int p[N/lnN]; // 素数分布定理
    bool com[N];
    
    for (int i=2; i<=n; i++) {
    	if (!com[i]) p[++p[0]]=i;
    	for (int j=1; j<=p[0] && i*p[j]<=n; j++) {
    		com[i*p[j]]=true;
    		if (i%p[j]==0) break;
    	}
    }
    

    素因数分解(筛法优化):

    int p[N/lnN], mfac[N];
    
    for (int i=2; i<=n; i++) {
    	if (!mfac[i]) p[++p[0]]=i;
    	for (int j=1; j<=p[0] && i*p[j]<=n; j++) {
    		mfac[i*p[j]]=p[j];
    		if (i%p[j]==0) break;
    	}
    }
    
    int fac[2 * sqrtN];  // 算术基本定理的推论
    while (x > 1) {
        fac[++fac[0]] = mfac[x];
        x /= mfac[x];
    }
    

    数论函数

    Bézout 定理:设 (a, bin mathbf{Z}), ((a, b) = d), 存在 (u,v), 使得 (ua+vb=d).

    算术基本定理(整数唯一分解定理):对于正整数 (a), 等式 (a=p_1^{e_1} p_2^{e_2}cdots p_n^{e_n}) 唯一确定.

    积性函数:对于 ((m,n)=1), (m,n∈mathbf{N}^*), 有 (f(mn)=f(m)f(n)). 要么 (f(n)=0, forall nin mathbf{N}^*), 要么 (f(1)=1).

    完全积性函数:对于一切 (m, ninmathbf{N}^*), 有 (f(mn)=f(m)f(n)).

    Möbius 函数

    [displaystyle mu(n) = egin{cases}1,quad & n=1,\ (-1)^k, quad & n=p_1 p_2cdots p_k,\ 0,quad & p^2 |n. end{cases} ]

    除数函数 ( au(n)):正整数 (n) 的正因数个数.

    [displaystyle au(n)=sum_{d|n} 1 = prod_{i=1}^k (e_i+1), ]

    其中 (n=p_1^{e_1} p_2^{e_2}cdots p_k^{e_k}) (唯一确定).

    除数和函数:

    [displaystylesigma(n)=sum_{d|n} d=prod_{i=1}^k frac{1-p_i^{e_i+1}}{1-p_i}, ]

    其中 (n=p_1^{e_1} p_2^{e_2}cdots p_k^{e_k}) (唯一确定). 积性函数.

    Euler 函数 (varphi(n)):不超过正整数 (n) 的正整数 (1,2,3,ldots ,n-1) 中与 (n) 互质的数的个数. 积性函数. (varphi(p)=p-1).

    [displaystylevarphi(n)=nprod_{i=1}^k (1-frac{1}{p_i}). ]

    void euler(int n) {
    	for (int i=2; i<=n; ++i) phi[i]=i;
    	for (int i=2; i<=n; ++i) if (phi[i]==i) 
    		for (int j=i; j<=n; j+=i) phi[j]=phi[j]/i*(i-1);
    }
    

    取整函数

    Gauss 函数 ([x]):不大于 (x) 的最大整数. 又称整数部分.

    一般地, 地板函数 $ lfloor x floor=[x] $, 天花板函数 $ displaystyle lceil x ceil=egin{cases} [x], & xin mathbf{Z}, \ [x]+1, & x otin mathbf{Z}end{cases} $, 小数部分 $ lbrace x brace=x-[x] $.

    常用性质:

    [[x]+[y]le [x+y]le [x]+[y]+1. ]

    任取 $ xinmathbf{R} $, 都有 $ displaystyleleft[x ight]+left[x+frac{1}{2} ight]=left[2x ight] $.

    [[x]cdot [y]le [xy]. ]

    [displaystyleleft[frac{x}{n} ight]=left[frac{[x]+{x} }{n} ight] = left[frac{[x]}{n}+frac{{x}}{n} ight]=left[frac{[x]}{n} ight]. ]

    C++ 的默认取整方式为 向 0 取整。注意与取整函数的区别。

    线性同余方程

    拓展欧几里得算法:

    void exgcd(const int a, const int b, int &g, int &x, int &y) {
        if (!b) g=a, x=1, y=0;
        else exgcd(b, a%b, g, y, x), y -= x*(a/b);
    }
    

    若方程 (ax+by=c) ((a,b,cinmathbf{Z})) 的一组整数解为 ((x_0,y_0)), 则它的任意整数解可以写成 ((x_0+kb',y_0-ka')), 其中 (displaystyle a'=frac{a}{gcd(a,b)}), (displaystyle b'=frac{b}{gcd(a,b)}), (displaystyle kinmathbf{Z}).

    模线性方程组:

    解方程 (axequiv bpmod n): (ax-b) 即为 (n) 的倍数. 设 (ax-b=ny), 移项得 (ax-ny=b), 解线性同余方程即可.

  • 相关阅读:
    【LeetCode OJ】Remove Element
    【LeetCode OJ】Remove Duplicates from Sorted Array
    【LeetCode OJ】Swap Nodes in Pairs
    【LeetCode OJ】Merge Two Sorted Lists
    【LeetCode OJ】Remove Nth Node From End of List
    【LeetCode OJ】Two Sum
    【LeetCode OJ】Majority Element
    最长公共子序列问题
    php fopen与file_get_contents的区别
    PHP 技巧集合
  • 原文地址:https://www.cnblogs.com/greyqz/p/number.html
Copyright © 2020-2023  润新知