• 【数论】基础数论


    基础数论

    素数

    Eratosthenes 筛法

    bool isp[maxn];
    void shai() {
        isp[1] = 0; for (int i = 2; i <= n; ++i) isp[i] = 1; 
        for (int i = 2; i * i <= n; ++i) {
            if (!isp[i]) continue ;
            for (int j = 2 * i; j <= n; j += i) isp[j] = 0; 
        }
    }
    

    欧拉筛 O(n)

    int pri[maxn]; bool isp[maxn];
    void shai() {
        int c1 = 0; 
        for (int i = 2; i <= n; ++i) {
            if (!isp[i]) pri[++c1] = i;
            for (int j = 1; j <= c1 && i * pri[j] <= n; ++j) {
                isp[i * pri[j]] = 1;
                if (i % pri[j] == 0) break; 
            }
        }
    }
    

    由于欧拉筛的每个数都是由它的最小质因子筛掉的,所以欧拉筛可以用来预处理每个数的最小质因子。

    性质:每个数的质因子最多有 (O(log))

    证明:就算全都是 (2),也只有 (O(log))

    费马二平方定理

    素数 p 在模 4 意义下有 3 种情况

    1. (p = 2)
    2. (pequiv 1(mod~4))
    3. (pequiv 3(mod~4))

    其中 (p=2)(pequiv 1(mod~4))(p) 总可以表示成整数 (x^2+y^2),且这种表示是唯一的

    Gcd

    定理 1:(gcd(a,b))(a)(b) 的线性组合中最小的正整数

    证明:令 (g=gcd(a,b))(s)(a)(b) 的线性组合中最小的正整数

    (g|a,g|b),所以 (g|(ax+by)),所以 (g|s),又因为 (g>0,s>0),所以 (gle s)

    (q=lfloorfrac{a}{s} floor),我们得到 (r=amod s=a-qs=a-q(ax+by)=a(1-qx)+b(-qy))

    也就是说 (r) 也是 (a)(b) 的一个线性组合,由于 (0le r<s),所以 (r=0),所以有 (s|a),同理有 (s|b)

    所以 (s|g),又因为 (s>0,g>0),所以 (sle g)

    综上可得 (s=g)

    定理 2:(gcd(ax, bx) = xgcd(a, b))

    证明:显然

    定理 3:(gcd(a, b) = gcd(a - b, b))

    证明:

    定理 4:$gcd(a, b) = gcd(b,a mod b) $

    证明:

    定理 5:(gcd(a, b) imes lcm(a, b) = ab)

    证明:

    (g=gcd(a,b),l=lcm(a,b),a=xg,b=yg)

    (lcm(a,b)=lcm(xg,yg)=glcm(x,y)=gxyRightarrow gcd(a,b)*lcm(a,b)=gxgy=ab)

    定理 6:(gcd(a^n-1,a^m-1)=a^{gcd(n,m)}-1)

    证明:

    ((a^n-1,a^m-1)=(a^n-a^m,a^m-1)=(a^m(a^{n-m}-1),a^m-1))

    显然 (a^m)(a^m-1) 互质

    所以我们得到 ((a^{n-m}-1,a^m-1)),也就是说我们可以对指数做辗转相除

    所以最后一定能得到 (a^{(n,m)}-1)

    定理 7:(lcm(a_1,a_2,...a_n)=frac{1元gcd之积*3元gcd之积...}{2元gcd之积*4元gcd之积...})

    首先 (lcm) 肯定可以对于每个素因子单独考虑

    我们现在仅考虑素数 (p_i),不妨设 (b_i)(a_i) 素因子分解之后 (p_i) 的指数

    注意到 (p) 的贡献为 (max(b_1,b_2,cdots,b_n))

    这个 (max) 可以看做是全集的 (max),那么我们直接套 (max-min) 容斥,就能得到上述式子

    欧几里得算法

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

    复杂度 (O(log n))

    证明:

    (a_0)(a_1) 表示初始的两个数。

    数列 (a_i = a_{i-2}~\%~a_{i-1}) 直到 (a_k = 0),最大公约数即为 (a_{k-1})

    可以发现 (a_ileq a_{i-2} / 2),也就是说,每两个数减小至少一半,所以复杂度是 (O(lon))

    证明:

    分情况讨论:

    (a_{i-1}leq a_{i-2}/2) ,则 (a_{i}leq a_{i-2} / 2)

    否则 (a_{i-1}>a_{i-2} / 2),则 (a_{i} = a_{i-2}-a_{i-1}),则 (a_ileq a_{i-2} / 2)

    扩展欧几里得算法 ExGcd

    (ax+by=(a,b)) 利用扩展欧几里得算法可以找出一对满足条件的整数x,y。当然,这一对x,y是不唯一的。

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

    证明 : (ax+by=(a,b))
    利用 ((a,b)=(b,a\%b)) 可以不断递归,到底层 (b = 0) 则可解出 x 和 y

    约数和公式

    (n = p_1^{a_1}*p_2^{a_2}*p_3^{a_3}*...*p_m^{a_m})

    n 的所有约数的和为 ((1 + p_1+p_1^2+p_1^3+...+p_1^{a_1})(1 + p_2+p_2^2+p_2^3+...+p_2^{a_2})...(1 + p_m+p_m^2+p_m^3+...+p_m^{a_m}))
    考虑到每个括号中都是一个级数(大概吧),然后就能化简成
    (prod_{i=1}^{m}frac{p_i^{(a_i+1)}-1}{p_i-1}) 是不是很神奇

    证明:感性理解一下,这个乘法类似于组合数学中整数拆分的思想======= 自己yy 关于下面的哪个级数。
    (S(n)=1+ax+ax^2+ax^3+...+ax^n=sum_{i=0}^{n}ax^i Rightarrow xS(n)=sum_{i=1}^{n+1}ax^i Rightarrow S(n)=frac{xS(n)-S(n)}{x-1}=frac{x^{n+1}-1}{x-1})

    (O(sqrt n) 求所有约数)

    for(int i = 1; i * i <= x; ++i){
    	if(x % i == 0){
    		//i 是一个约数
        	if(x != i * i) // x / i 是一个约数
        }	
    }
    

    裴蜀定理

    对于整数 (a,b) 以及其最大公因数 (d),一定有整数 (x,y),使得 (ax + by = d)

    对于不定方程 (ax+by=c) 有整数解的充要条件是 (gcd(a,b)|c)

    证明:令 (g= gcd(a,b ))

    充分性: 已知 (g|c)

    (g)(a)(b) 线性组合,证完了

    必要性:已知 (ax+by=c) 有整数解

    所以 (c)(a)(b) 的线性组合

    所以 (g|c)

    在模意义下,可以使得 (x)(y) 为正整数 ????

    裴蜀定理可拓展的到多个数

    (sum_{i|n}sum_{j|n}[gcd(i,j)=1])

    一种显然得方法是枚举 n 的约数,复杂度 (O(n)),考虑优化

    (n=prod_{i=1}^mp_i^{a_i})

    (sum_{i_1|p_1^{a_1}}...sum_{i_m|p_m^{a_m}}sum_{j_1|p_1^{a_1}}...sum_{j_m|p_m^{a_m}}[gcd(i_1*...*i_m,j1*...*j_m)=1])

    (sum_{i_1|p_1^{a_1}}...sum_{i_m|p_m^{a_m}}sum_{j_1|p_1^{a_1}}...sum_{j_m|p_m^{a_m}}[gcd(i_1,j_1)=1]*[gcd(i2,j2)=1]*...*[gcd(i_m,j_m)=1])

    (sum_{i_1=0}^{a_1}sum_{j_1=0}^{a_1}[min(i_1,j_1)=0]...sum_{i_m=0}^{a_m}sum_{j_m=0}^{a_m}[min(i_m,j_m)=0])

    对于 (sum_{i=0}^asum_{j=0}^a[min(i,j)=0]=2a+1)

    (Ans=prod_{i=1}^m2a_i+1)

    定义:集合 (S) 为一个模,仅当 (Ssubseteq Z),且 (S) 满足对加减法封闭,即 (forall m,n in S,mpm n in S)

    生成模::集合 (T) 的生成模是,最小的模 (S) ,使得 (Tsubseteq S)

    实际意义:若 $ain T,bin T,a+b otin TORa-b otin T $,将 (a+b,a-b) 加入 (T) 。不断进行。

    定理:集合 (S) 为一个非零模,当且仅当 (S) 中的所有元素都是一个正整数的倍数。

    证明:设 (d)(S) 中的最小正整数。假设存在一个整数 (x)(x) 不是 (d) 的倍数。则 (x\%d e0,且x \%d < d),故 (x\%d)(S) 中的最小正整数,与 (d)(S) 中的最小正整数矛盾

    定理:(gcd(a,b)) 是 a 和 b 的生成模 (S) 中最小正整数。

    证明:

    设 d 是 (S) 中的最小正整数,(gcd(a,b) in S),故 (d~|~gcd(a,b)),即 (dleq gcd(a,b))

    (din S),所以 (d)(a)(b) 线性组合,所以 (gcd(a,b) ~|~d),即 (gcd(a,b) leq d)

    所以 (d=gcd(a,b))

    同余和取模

    先看三个公式:(a+b) mod m = ((a mod m) + (b mod m))mod m
    (a-b) mod m = ((a mod m) - (b mod m) + m)mod m
    ab mod m = (a mod m)(b mod m)mod m

    同余的性质

    1. 自反性:(aequiv a(mod m))
    2. 对称性:若 (aequiv b(mod m)),则 (bequiv a(mod m))
    3. 同加性:若 (aequiv b(mod m)),则 (a+cequiv b+c(mod m))
    4. 同减性:若 (aequiv b(mod m)),则 (a-cequiv b-c(mod m))
    5. 同乘性:若 (aequiv b(mod m)),则 (acequiv bc(mod m))
    6. 同幂性:若 (aequiv b(mod m)),则 (a^nequiv b^n(mod m))
    7. 推论1:若 (amod p=k)(amod q=k),且 (gcd(p,q)=1),则 (amod pq=k)
    8. 注意:同余不满足同除性,即 a $$div$$ n $$ otequiv$$ b $$div$$ n (mod m)

    幂取模

    (a^nmod p)

    思路:在快速幂的过程中取模

    ll pow_mod(ll x, ll n) {
        ll s = 1;
        for(; n; n >>= 1) {
            if(n & 1) s = s * x % p;
            x = x * x % p;
        } return s;
    }
    

    对于同余方程 (axequiv d(mod~m))(m) 为质数,d = (gcd(a,m))

    (axequiv d(mod~m)Rightarrow ax+my=d) 利用 (exgcd) 算法可以求得一组解,但要是于要求是最小正整数解。

    考虑 (ax+my=d),令 (x=x-m,y=y+a)(ax+by) 依然 (=d),且 (x) 变小了,只告诉我们 (x) 可以对 (m) 取模。

    但是可不可以更小。考虑令 (x=x-m,y=y+a),也可以让 (x=x-m/d,y=y+a/d),也就是说 (x) 可以对 (m/d) 取模

    BSGS

    用于求解 (a^xequiv y(mod~p)) (p) 是一个素数

    (q=sqrt p) 考虑最终答案 (x) 一定在 ([0,p-1])

    在考虑两个数列 (S=[a^0,a^1,...,a^q],T=[a^0,a^q,a^{2q}...,a^{q^2}])

    对于任意的 x,都可以用 (t_1in S,t_2 in T) 表示,即 (a^xequiv a^{t_1+t_2}equiv y Rightarrow a^{t_2}equiv y*{a^{t_1}}^{-1})

    (t_2) 放到 hash 表里,枚举 (t_1),查表即可。时间复杂度 (O(sqrt n))

    对于 p 不是素数的情况,可以用 exBSGS

    拓展欧拉定理

    (egin{equation}~a^c~equiv~left{ egin{array}\ a^{c~Mod~phi(m)} &gcd(a,m)~=~1 \ a^c &gcd(a,m)~ eq~1~and~c~<~phi(m) \ a^{c~Mod~phi(m)~+~phi(m)} & gcd(a,m)~ eq~1~and~c~geq~phi(m) end{array} ight. end{equation})

    逆元

    概念:对于正整数 $a $ 和 (m),如果有 (axequiv 1mod(m)),并且 (gcd(a,m)=1),则把这个同余方程中 (x) 的最小正整数解叫做 $ a mod(m)$ 的逆元

    作用:在求解除法取模问题 ((a/b)\%m) 时,我们发现除法不能直接取模,解决方法就是用乘法逆元,除以一个数取模等于乘以这个数的逆元再取模,即a/b=(a * inv(b))%m

    证明:(frac{a}{b}equiv kmod(m)Rightarrow frac{a}{b*b^{-1}}equiv frac{k}{b^{-1}}mod(m) Rightarrow aequivfrac{k}{b^{-1}}mod(m)Rightarrow a*b^{-1}equiv kmod(m))

    当然对于 ((a/b)\%m),还可将其转换为 ((a\%bm)/b)

    证明:令 ((a/b)\%m=x),则 (a/b=km+xRightarrow a=kmb+bxRightarrow a\%bm=bxRightarrow(a\%bm)/b=x)

    求法:

    1.费马小定理

    要求:p 为素数,然后求 $$a^{p-2}~mod ~p$$

    2.扩展欧几里得

    要求:gcd(a,m)=1,ax $$equiv$$ 1(mod m)可以转换为ax-my=1,把y写成+的形式就是ax+my=1,因为a与m互素,所以可以直接套用扩展欧几里得求出x即可

    代码:

    int inv(int a,int m){//计算a在模m下的逆
    	int d,x,y;
      	exgcd(a,m,d,x,y);
      	return d == 1 ? (x+n)%n :-1;
    }
    

    3.线性求逆元

    求一组数模m的逆元

    (m=k*i+rRightarrow k*i+requiv 0mod(m)Rightarrow k+r*i^{-1}equiv 0 mod(m))
    (Rightarrow k*r^{-1}+i^{-1}equiv 0mod(m)Rightarrow i^{-1}equiv-k*r^{-1}mod(m)Rightarrow i^{-1}equiv -m/i*(m\%i)^{-1})

    另外:1 -> p-1 的所有数的逆元对应了 1 -> p-1 的所有数,既是单射也是满射

    #include<iostream>
    #include<cstdio>
    #define maxn 3000010
    #define ll long long
    using namespace std;
    
    int n, m;
    ll inv[maxn];
    
    int main(){
    	cin >> n >> m; inv[1] = 1;
    	for(int i = 2; i <= n; ++i){
    		inv[i] = -1ll * (m / i) * inv[m % i];
    		inv[i] = (inv[i] % m + m) % m;
    	}
    	for(int i = 1; i <= n; ++i) printf("%lld
    ", inv[i]);
    	return 0;
    }
    	
    

    剩余系

    完全剩余系

    (p) 意义下的完全剩余系为 ({0,1,2,3,...,p-1})

    性质:

    1. (a_i) 构成了模 (p) 的完全剩余系,(gcd(m,p)=1)(kin Z),则 (k+ma_i) 也构成模 (p) 的完全剩余系

      证明:

      假设 (k+ma_iequiv k+ma_j(mod~p))

      (ma_iequiv ma_j(mod~p)) 两边同乘 (m) 在模 (p) 意义下的逆元

      (a_iequiv a_j(mod~p)) 不成立

    简化剩余系(缩系)

    (p) 的缩系为 ({a_i})(0<a_i<p),且 (gcd(p, a_i)=1),这样的 (a_i)(varphi(p))

    性质:

    1. (a_i) 构成了模 (p) 的简化剩余系,(gcd(m,p)=1),则 (ma_i) 也构成模 (p) 的完全剩余系

    2. 如果 (gcd(p,p')=1)(a_i) 遍历模 (p) 的一个缩系,(a_i') 遍历模 (p') 的一个缩系,则 (a_i*p'+a_i'*p) 遍历 (pp') 的缩系

      证明:

    (a)(p) 为正整数,且 (gcd(a,p)=1),称满足 (a^requiv 1(mod~p)) 的最小正整数 (r)(a)(p) 的阶(可以写成 (Ord_p(a))

    由欧拉定理,(a^{varphi(p)}equiv 1(mod~p)),所以 (Ord_p(a)~|~varphi(p))

    求阶只能从小到大枚举 ==

    原根

    (a)(p) 为正整数,且 (gcd(a,p)=1),称满足 (Ord_p(a)=varphi(p))(a) 为模 (p) 的一个原根

    关于原根的几个性质

    1. 注意到所有的素数都有原根
    2. 当正整数 (p) 有原根时,原根的个数为 (varphi(varphi(p)))
    3. (p) 的原根是 (g),那么 (g,g^2,...,g^{varphi(p)}) 构成了模 (p) 简化剩余系

    求素数原根的方法:

    从小到大枚举 (d,din [2,p-1]),令 $a_i $ 为 (varphi(p )) 的素因子,验证 (d^{frac{varphi(p)}{a_i}}equiv 1(mod~p)) 是否都不成立,如果都不成立,那么 d 就是模 (p) 的一个原根

    这种方法的证明:

    假设对于 (d^{frac{varphi(p)}{a_i}}equiv 1(mod~p)) 均不成立,但存在 (k,k<varphi(p)),使得 (d^kequiv1(mod~p))

    那么 (gcd(k,varphi(p))<p) 并且 (gcd(k,varphi(p))) 一定整除 (frac{varphi(p)}{a_i}) 中的一个,不妨设它整除 (frac{varphi(p) }{a_i})

    考虑在模意义下的等式 (kx+varphi(p)yequiv gcd(k,varphi(p))~(mod~varphi(p))),容易发现一定存在正整数解

    我们知道 (d^{kx+varphi(p)y}equiv 1(mod~p)),所以 (d^{gcd(k,varphi(p))}equiv 1(mod~p)),而 (gcd(k,varphi(p))~|~frac{varphi(p)}{a_i}),这与假设矛盾

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define maxn 500010
    #define ll long long
    using namespace std;
    
    int p, a[maxn], c1;
    
    ll pow_mod(ll x, ll n) {
        ll s = 1;
        for (; n; n >>= 1) {
            if (n & 1) s = s * x % p;
            x = x * x % p; 
        } return s; 
    }
    
    int ans; 
    int main() {
        cin >> p; int n = p - 1; 
        for (int i = 2; i * i <= n; ++i) 
            if (n % i == 0) {
                a[++c1] = i;
                while (n % i == 0) n /= i; 
            }
        for (int i = 2; i < p; ++i) {
            bool F = 1; 
            for (int j = 1; j <= c1; ++j)
                if (pow_mod(i, (p - 1) / a[j]) == 1) { F = 0; break; }
            if (F) { ans = i; break; } 
        } cout << ans << endl; 
        return 0; 
    }
    
    
    

    二次剩余

    定义:对于整数 (x,d,p),如果存在 (x),使得 (x^2equiv d(mod~p)),则称 (d)(p) 的二次剩余

    以下讨论的皆是质数的二次剩余,即 (p) 是质数。

    如何一个数是否是一个二次剩余

    (x^2equiv a(mod~p)) 设原根为 (b,x=b^s,a=b^t)

    (b^{2s}equiv b^t(mod~p)Rightarrow 2sequiv t(mod~p-1))

    因为 p - 1 一定是一个偶数,所以如果 (t) 为奇数,原式无解

    考虑 (t) 为偶数的情况,(1le s le p - 1),所以 (s_1=t/2,s_2=t/2+(p-1)/2)

    所以 (x=b^{t/2})(x=b^{t/2}b^{(p-1)/2}=-b^{t-2})

    以上的算法是在知道原根的情况下,并且复杂度与 (p) 同阶,一般没啥用???

    考虑别的方法。

    勒让德符号

    定义:1.png

    定理:((frac{a}{p})equiv a^{frac{p-1}{2}}(mod~p)),方程有解当且仅当 (a^{frac{p-1}{2}}equiv 1(mod~p))

    证明:

    ((frac{a}{p})=1) 时,方程 (x^2equiv a(mod~p)) 有解,则 (xequiv a^{frac{1}{2}}(mod~p))。我们知道 (x^{p-1}equiv 1(mod~p)),所以 (a^{frac{p-1}{2}}equiv 1(mop~p))

    当 $$

    定理:对于质数 p,只有 (frac{p-1}{2}) 个二次剩余

    证明:对于 (1le u,vle p-1,u+v=p)(p|(u+v)),则 (p|(u+v)(u-v)),则 (p|(u^2-v^2)),则 (u^2equiv v^2(mod~p))

    定理:((a+b)^pequiv a^p+b^p(mod~p))

    证明:

    ((a+b)^p=sum_{i=0}^pa^ib^{p-i}C_p^i)

    (i) 不等于 0 和 p 时,(C_p^i=frac{p!}{i!(p-i)!}) 中的 p 因为是质数,不可能被约掉,所以一定是 p 的倍数

  • 相关阅读:
    history对象
    排序算法总结
    Boltzmann机
    Sort Colors
    First Missing Positive
    Sort List
    Insertion Sort List
    Merge Two Sorted Lists
    Merge Sorted Array
    Sum Root to Leaf Numbers
  • 原文地址:https://www.cnblogs.com/duzhiyuan/p/12049402.html
Copyright © 2020-2023  润新知