• 【数论】基础数论


    基础数论

    素数

    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 的倍数

  • 相关阅读:
    10 种保护 Spring Boot 应用的绝佳方法
    Redis 如何分析慢查询操作?
    Spring Boot 主类及目录结构介绍
    Redis 再牛逼,也得设置密码!!
    Spring Data Redis 详解及实战一文搞定
    Spring Boot Redis Cluster 实战干货
    超详细的 Redis Cluster 官方集群搭建指南
    Redis Linux 安装运行实战全记录
    hdu 4790 Just Random (思路+分类计算+数学)
    poj 1328 Radar Installation(贪心)
  • 原文地址:https://www.cnblogs.com/duzhiyuan/p/12049402.html
Copyright © 2020-2023  润新知