数论学习笔记1

1.1 整除
  1. 如果 a   ∣   b a\ |\ b a  b b   ∣   c b\ |\ c b  c ,那么 a   ∣   c a\ |\ c a  c

  2. a   ∣   b a\ |\ b a  b a   ∣   c a\ |\ c a  c 等价于对任意的整数 x x x y y y ,有 a   ∣   ( b ∗ x + c ∗ y ) a\ |\ (b*x+c*y) a  (bx+cy)

  3. m ≠ 0 m\not= 0 m=0 ,那么 a   ∣   b a\ |\ b a  b 等价于 ( m ∗ a )   ∣   ( m ∗ b ) (m*a)\ |\ (m*b) (ma)  (mb)

  4. 设整数 x x x y y y 满足下式: a ∗ x + b ∗ y = 1 a*x+b*y = 1 ax+by=1 ,且 a   ∣   n a\ |\ n a  n b   ∣   n b\ |\ n b  n ,那么 ( a ∗ b )   ∣   n (a*b)\ |\ n (ab)  n

    证明:因为 a   ∣   n a\ |\ n a  n b   ∣   n b\ |\ n b  n

    根据性质 3 可得: ( a ∗ b )   ∣   ( b ∗ n ) (a*b)\ |\ (b*n) (ab)  (bn) ( a ∗ b )   ∣   ( a ∗ n ) (a*b)\ |\ (a*n) (ab)  (an)

    再由性质 2 可得: ( a ∗ b )   ∣   ( a ∗ n ∗ x + b ∗ n ∗ y ) (a*b)\ |\ (a*n*x+b*n*y) (ab)  (anx+bny)

    其中: a ∗ n ∗ x + b ∗ n ∗ y = n ∗ ( a ∗ x + b ∗ y ) = n ∗ 1 = n a*n*x+b*n*y=n*(a*x+b*y)=n*1=n anx+bny=n(ax+by)=n1=n ,所以: ( a ∗ b )   ∣   n (a*b)\ |\ n (ab)  n

  5. b = q ∗ d + c b=q*d+c b=qd+c ,那么 d   ∣   b d\ |\ b d  b 的充要条件是 d   ∣   c d\ |\ c d  c

1.2 同余
  1. 自反性: a ≡ a   ( m o d   m ) a\equiv a\ (mod \ m) aa (mod m)

  2. 对称性:若 a ≡ b   ( m o d   m ) a \equiv b\ (mod \ m) ab (mod m) ,则 b ≡ a   ( m o d   m ) b \equiv a \ (mod \ m) ba (mod m)

  3. 传递性:若 a ≡ b   ( m o d   m ) a \equiv b\ (mod \ m) ab (mod m) b ≡ c   ( m o d   m ) b\equiv c \ (mod \ m) bc (mod m) ,则 a ≡ c   ( m o d   m ) a\equiv c \ (mod \ m) ac (mod m)

  4. 同加性:若 a ≡ b   ( m o d   m ) a\equiv b\ (mod \ m) ab (mod m) ,则 a + c ≡ b + c   ( m o d   m ) a+c\equiv b+c\ (mod\ m) a+cb+c (mod m)

  5. 同乘性:若 a ≡ b   ( m o d   m ) a\equiv b\ (mod\ m) ab (mod m) ,则 a ∗ c ≡ b ∗ c   ( m o d   m ) a*c\equiv b*c\ (mod\ m) acbc (mod m)

    ​ 若 a ≡ b   ( m o d   m ) a\equiv b\ (mod\ m) ab (mod m) c ≡ d   ( m o d   m ) c\equiv d\ (mod\ m) cd (mod m),则 a ∗ c ≡ b ∗ d   ( m o d   m ) a*c\equiv b*d\ (mod\ m) acbd (mod m)

  6. 同幂性:若 a ≡ b   ( m o d   m ) a\equiv b\ (mod\ m) ab (mod m) ,则 a n ≡ b n   ( m o d   m ) a^n\equiv b^n\ (mod\ m) anbn (mod m)

  7. 推论1: a ∗ b   m o d   k = ( a   m o d   k ) ∗ ( b   m o d   k )   m o d   k a*b\ mod\ k = (a\ mod\ k)*(b\ mod\ k)\ mod\ k ab mod k=(a mod k)(b mod k) mod k

  8. 推论2:若 a   m o d   p = x a\ mod\ p = x a mod p=x a   m o d   q = x a\ mod\ q=x a mod q=x p p p q q q 互质,则 a   m o d   p ∗ q = x a\ mod\ p*q=x a mod pq=x

    证明:因为 a   m o d   p = x a\ mod\ p=x a mod p=x a   m o d   q = x a\ mod\ q=x a mod q=x p p p q q q 互质

    ​ 则一定存在整数 s s s t t t ,使得 a = s ∗ p + x a=s*p+x a=sp+x a = t ∗ q + x a=t*q+x a=tq+x

    ​ 所以, s ∗ p = t ∗ q s*p= t*q sp=tq

    ​ 则一定存在整数 r r r ,使 s = r ∗ q s=r*q s=rq

    ​ 所以, a = r ∗ p ∗ q + x a=r*p*q+x a=rpq+x ,得出: a   m o d   p ∗ q = x a\ mod\ p*q = x a mod pq=x

1.3 最大公约数
  1. 辗转相除法(欧几里得算法)

    原理: G C D ( x , y ) = G C D ( x , y − x ) GCD(x, y) = GCD(x, y-x) GCD(x,y)=GCD(x,yx)

    证明:设 z   ∣   x z\ |\ x z  x z   ∣   y z\ |\ y z  y ,则 z   ∣   ( y − x ) z\ |\ (y-x) z  (yx)

    ​ 设 z z z 不是 x x x 的因子,则 z z z 不是 y y y y − x y-x yx 的公因子。

    ​ 设 z   ∣   x z\ |\ x z  x z z z 不是 y y y 的因子,则 z z z 不是 x x x y − x y-x yx 的公因子。

    推论: G C D ( x ,   y ) = G C D ( y ,   x   m o d   y ) GCD(x,\ y) = GCD(y,\ x\ mod\ y) GCD(x, y)=GCD(y, x mod y)

    证明:设 x > y x > y x>y ,则存在整数 a a a b b b ,使得 x = a y + b x = ay+b x=ay+b

    ​ 设 d = G C D ( x ,   y ) d = GCD(x,\ y) d=GCD(x, y) ,则 d   ∣   y d\ |\ y d  y d   ∣   ( a y + b ) d\ |\ (ay+b) d  (ay+b) ,得到 d   ∣   b d\ |\ b d  b,而 b = x   m o d   y b = x\ mod\ y b=x mod y

    ​ 所以 d = G C D ( y , x   m o d   y ) d = GCD(y, x\ mod\ y) d=GCD(y,x mod y)

    时间复杂度证明:要证明 x   m o d   y ≤ m i n ( y ,   x   m o d   y ) / 2 x\ mod\ y \le min(y,\ x\ mod\ y)/2 x mod ymin(y, x mod y)/2

    x > y x > y x>y y ≤ x / 2 y \le x/2 yx/2 ,那么 x   m o d   y < y ≤ y ≤ x / 2 x\ mod\ y < y \le y \le x/2 x mod y<yyx/2

    x > y x > y x>y y > x / 2 y > x/2 y>x/2 ,那么 x   m o d   y = x − y ≤ x / 2 x\ mod\ y = x-y \le x/2 x mod y=xyx/2

    x < y x<y x<y ,那么 x   m o d   y = x x\ mod\ y = x x mod y=x

    因此可以知道每次都至少减少一半,复杂度为 O ( l o g   m i n ( x ,   y ) ) O(log\ min(x,\ y)) O(log min(x, y))

    inline int gcd(int a, int b) {
        while (b) {
            int r = a % b;
            a = b, b = r;
        }
        return a;
    }
    
  2. 二进制算法(提高GCD的效率)

    x = y x=y x=y ,则 G C D ( x , y ) = x GCD(x,y)=x GCD(x,y)=x ,否则:

    (1)若 x x x y y y 均为偶数,则 G C D ( x ,   y ) = 2 G C D ( x / 2 ,   y / 2 ) GCD(x,\ y) = 2GCD(x/2,\ y/2) GCD(x, y)=2GCD(x/2, y/2)

    (2)若 x x x 为奇数, y y y 为偶数,则 G C D ( x ,   y ) = G C D ( x ,   y / 2 ) GCD(x,\ y) = GCD(x,\ y/2) GCD(x, y)=GCD(x, y/2)

    (3)若 x x x 为偶数, y y y 为奇数,则 G C D ( x ,   y ) = G C D ( x / 2 ,   y ) GCD(x,\ y) = GCD(x/2,\ y) GCD(x, y)=GCD(x/2, y)

    (4)若 x x x 为奇数, y y y 为奇数,则 G C D ( x ,   y ) = G C D ( x ,   x − y ) GCD(x,\ y) = GCD(x,\ x-y) GCD(x, y)=GCD(x, xy)

    inline int gcd(int a, int b) {
        int i, j;
        if (x == 0) return y;
        if (y == 0) return x;
        for (i = 0; 0 == (x&1); i ++) x >>= 1;  // 去掉所有的 2
        for (j = 0; 0 == (y&1); j ++) y >>= 1;  // 去掉所有的 2
        if (j < i) i = j;   // 取小的,表示最大公约数的一部分因子 2 的 i 次方
        while (true) {
            if (x < y) x ^= y ^= x ^= y;        // 保证 x 大于等于 y
            if (0 == (x-=y)) return y << i;		// 等于 0 表示另一部分因子为 y
            while (0 == (x&1)) x >>= 1;         // 去掉所有的 2
        }
    }
    
  3. 基于值域预处理的快速GCD

    引入:我们需要求 G C D ( x ,   y ) GCD(x,\ y) GCD(x, y) ,可以把 x x x 分解,这样我们可以通过提前计算小部分的最大公约数存储在 g c d [ x ] [ y ] gcd[x][y] gcd[x][y] 中,这样就可以减少调用欧几里得算法的次数。

    假设要询问 G C D ( x ,   y ) GCD(x,\ y) GCD(x, y) ,将 x x x 分解为 x 1 ,   x 2 ,   …   ,   x n x_1,\ x_2,\ …\ ,\ x_n x1, x2,  , xn ,先算 g c d [ x 1 ] [ y ] gcd[x_1][y] gcd[x1][y] ,然后乘到 a n s ans ans 中,再将 y y y 除以 g c d [ x 1 ] [ y ] gcd[x_1][y] gcd[x1][y] ,因为这个因子已经计算,不能重复计数,然后是 x 2 ,   … x_2,\ … x2,  ,直到全部的贡献都算完然后乘到 a n s ans ans 中。

    inline int GCD(int x, int y) {
        int ans = 1;
        for (int i = 1; i <= n; i ++) {
            int tmp = gcd[fac[x][i]][y%fac[x][i]];
            y /= tmp, ans *= tmp;
        }
        return ans;
    }
    

    定理: ∀ x ∈ [ 1 ,   n ] \forall x \in [1,\ n] x[1, n] ,都可以分解成有序三元组 ( a ,   b ,   c )   ,   a ≤ b ≤ c (a,\ b,\ c)\ ,\ a\le b\le c (a, b, c) , abc ,且 a ,   b ,   c ∈ [ 1 ,   x ] ∪ P a,\ b,\ c \in [1,\ \sqrt{x}] \cup P a, b, c[1, x ]P P P P 是素数集合,使得 x = a × b × c   ( a ≤ b ≤ c ) x = a\times b\times c\ (a \le b \le c) x=a×b×c (abc)

    Question 1:如何求任意一个数 x x x 的分解?

    考虑线筛,若 x x x 为质数,显然 ( 1 ,   1 ,   x ) (1,\ 1,\ x) (1, 1, x) 是它的一个分解。

    x x x 为合数,设 p p p x x x 的最小质因子, ( a 0 ,   b 0 ,   c 0 ) (a_0,\ b_0,\ c_0) (a0, b0, c0) x / p x/p x/p 的一个分解;

    下面证 a 0 p ,   b 0 ,   c 0 a_0p,\ b_0,\ c_0 a0p, b0, c0 排序后是 x x x 的一个分解。

    • p ≤ x 4 p\le \sqrt[4]{x} p4x ,结合 a 0 ≤ x / p 3 a_0 \le \sqrt[3]{x/p} a03x/p ,可得 a 0 p ≤ x a_0p \le \sqrt{x} a0px
    • p > x 4 p>\sqrt[4]{x} p>4x
      • a 0 = 1 a_0=1 a0=1 时, a 0 p = p a_0p=p a0p=p ,它是一个质数,结论显然成立;
      • a 0 ≠ 1 a_0\not=1 a0=1 时,取 x / p x/p x/p 的最小质因子 q q q ,因为 q q q 也是 x x x 的质因子,所以 p ≤ q p\le q pq ,又由于 a 0 ,   b 0 ,   c 0 a_0,\ b_0,\ c_0 a0, b0, c0 x / p x/p x/p 不为 1 的因数,从而 q ≤ a 0 ≤ b 0 ≤ c 0 q\le a_0\le b_0\le c_0 qa0b0c0 p × a 0 × b 0 × c 0 > x p\times a_0\times b_0\times c_0 > x p×a0×b0×c0>x ,矛盾,不存在此情况。

    于是 a 0 p ,   b 0 , c 0 a_0p,\ b_0, c_0 a0p, b0,c0 排序后是 x x x 的一个分解。

    容易在 O ( n ) O(n) O(n) 的时间内预处理出 n \sqrt{n} n 内的数两两的最大公因数,下面考虑求 G C D ( x ,   y ) GCD(x,\ y) GCD(x, y)

    引理:若 r   ∣   a ,   r   ∣   b r\ |\ a,\ r\ |\ b r  a, r  b ,则 G C D ( a ,   b ) = r ⋅ G C D ( a / r , b / r ) GCD(a,\ b)=r\cdot GCD(a/r,b/r) GCD(a, b)=rGCD(a/r,b/r)

    这是显然的。

    ( a ,   b ,   c ) (a,\ b,\ c) (a, b, c) x x x 的一个分解,令 p 1 = y ,   r 1 = G C D ( a ,   p 1 ) p_1 = y,\ r_1=GCD(a,\ p_1) p1=y, r1=GCD(a, p1)

    r 1   ∣   a ,   r 1   ∣   p 1 r_1\ |\ a,\ r_1\ |\ p_1 r1  a, r1  p1 ,从而 G C D ( x ,   y ) = r 1 ⋅ G C D ( x / r 1 ,   p 1 / r 1 ) GCD(x,\ y) = r_1\cdot GCD(x/r_1,\ p_1/r_1) GCD(x, y)=r1GCD(x/r1, p1/r1)

    再令 p 2 = p 1 / r 1 ,   r 2 = G C D ( b ,   p 2 ) p_2=p_1/r_1,\ r2=GCD(b,\ p_2) p2=p1/r1, r2=GCD(b, p2) ,同上有 G C D ( x , y ) = r 1 r 2 ⋅ G C D ( x / ( r 1 r 2 ) ,   p 2 / r 2 ) GCD(x,y)=r_1r_2\cdot GCD(x/(r_1r_2),\ p2/r_2) GCD(x,y)=r1r2GCD(x/(r1r2), p2/r2)

    再令 p 3 = p 2 / r 2 ,   r 3 = G C D ( c ,   p 3 ) p_3=p_2/r_2,\ r_3=GCD(c,\ p_3) p3=p2/r2, r3=GCD(c, p3) ,同上有 G C D ( x ,   y ) = r 1 r 2 r 3 ⋅ G C D ( x / ( r 1 r 2 r 3 ) ,   p 3 / r 3 ) GCD(x,\ y) = r_1r_2r_3\cdot GCD(x/(r_1r_2r_3),\ p_3/r_3) GCD(x, y)=r1r2r3GCD(x/(r1r2r3), p3/r3)

    易知此时 G C D ( x / ( r 1 r 2 r 3 ) ,   p 3 / r 3 ) = 1 GCD(x/(r_1r_2r_3),\ p_3/r_3)=1 GCD(x/(r1r2r3), p3/r3)=1 ,故 G C D ( x ,   y ) = r 1 r 2 r 3 GCD(x,\ y)=r_1r_2r_3 GCD(x, y)=r1r2r3

    由于我们预处理了 n \sqrt{n} n 内所有数两两的 G C D GCD GCD ,故上述算法过程可以做到 O ( 1 ) O(1) O(1)

    const M = 1e6, N = 1e3;
    int prime[M+5], tot = 0;
    int fac[M+5][3];
    int gcd[N+5][N+5];
    bool check[M+5];
    // 线性筛分解 x 为 (a, b, c) 
    void Sieve() {
        fac[1][0] = fac[1][1] = fac[1][2] = 1;
        for (int i = 2; i <= M; i ++) {
            if (! check[i]) {
                prime[++ tot] = i;
                fac[i][0] = fac[i][1] = 1, fac[i][2] = i;
            }
            for (int j = 1; j <= tot && i*prime[j] <= M; j ++) {
                int k = i*prime[j];
                check[k] = true;
                fac[k][0] = fac[i][0] * prime[j];
                fac[k][1] = fac[i][1], fac[k][2] = fac[i][2];
                if (fac[k][0] > fac[k][1]) swap(fac[k][0], fac[k][1]);
                if (fac[k][1] > fac[k][2]) swap(fac[k][1], fac[k][2]);
                if (i % prime[j] == 0) break;
            }
        }
    }
    
    // 预处理 N = sqrt(M) 内的 GCD
    void init_gcd() {
        for (int i = 1; i <= N; i ++) {
            gcd[i][0] = gcd[0][i] = i;
            for (int j = 1; j <= i; j ++)
                gcd[i][j] = gcd[j][i] = gcd[j][i%j];
        }
    }
    
    // 接着求 GCD 就变成了这样 O(1)
    int GCD(int a, int b) {
        int res = 1;
        for (int i = 0, r; i < 3; i ++) {
            if (fac[a][i] > N) {
                if (b % fac[a][i]) r = 1;
                else r = fac[a][i];
            }else r = gcd[fac[a][i]][b%fac[a][i]];
            b /= r;
         	res = res * r;
        }
        return res;
    }
    
  4. 最小公倍数

    定理: a a a b b b 两个数的最大公约数乘以它们的最小公倍数就等于 a a a b b b 本身的乘积。

    证明:设 a = P 1 α 1 P 2 α 2 … P n α n a = P_1^{\alpha_1} P_2^{\alpha_2}…P_n^{\alpha_n} a=P1α1P2α2Pnαn b = P 1 β 1 P 2 β 2 … P n β n b = P_1^{\beta_1} P_2^{\beta_2}…P_n^{\beta_n} b=P1β1P2β2Pnβn α i ,   β i ≥ 0 \alpha_i,\ \beta_i \ge 0 αi, βi0 1 ≤ i ≤ n 1 \le i \le n 1in

    ​ 显然 G C D ( a ,   b ) = P 1 m i n ( α 1 ,   β 1 ) P 2 m i n ( α 2 ,   β 2 ) … P n m i n ( α n ,   β n ) GCD(a,\ b) = P_1^{min(\alpha_1,\ \beta_1)}P_2^{min(\alpha_2,\ \beta_2)}…P_n^{min(\alpha_n,\ \beta_n)} GCD(a, b)=P1min(α1, β1)P2min(α2, β2)Pnmin(αn, βn)

    L C M ( a ,   b ) = P 1 m a x ( α 1 ,   β 1 ) P 2 m a x ( α 2 ,   β 2 ) … P n m a x ( α n ,   β n ) LCM(a,\ b) = P_1^{max(\alpha_1,\ \beta_1)}P_2^{max(\alpha_2,\ \beta_2)}…P_n^{max(\alpha_n,\ \beta_n)} LCM(a, b)=P1max(α1, β1)P2max(α2, β2)Pnmax(αn, βn)

    a ⋅ b = P 1 α 1 + β 1 P 2 α 2 + β 2 … P n α n + β n a\cdot b= P_1^{\alpha_1+\beta_1}P_2^{\alpha_2+\beta_2}…P_n^{\alpha_n+\beta_n} ab=P1α1+β1P2α2+β2Pnαn+βn

    ​ 对于 ∀ i ∈ [ 1 ,   n ] \forall i \in [1,\ n] i[1, n] α i + β i = m i n ( α i ,   β i ) + m a x ( α i ,   β i ) \alpha_i+\beta_i=min(\alpha_i,\ \beta_i) + max(\alpha_i,\ \beta_i) αi+βi=min(αi, βi)+max(αi, βi)

    ​ 所以 G C D ( a ,   b ) ⋅ L C M ( a ,   b ) = a ⋅ b GCD(a,\ b)\cdot LCM(a,\ b) = a\cdot b GCD(a, b)LCM(a, b)=ab

    inline ll lcm(int a, int b) {
        return (ll) a/gcd(a, b) * b;
    }
    
  5. 扩展欧几里得算法

    扩展欧几里得算法是用来在已知 ( a ,   b ) (a,\ b) (a, b) 时,求解一组 ( x ,   y ) (x,\ y) (x, y) ,使得 a x + b y = G C D ( a ,   b ) ax+by=GCD(a,\ b) ax+by=GCD(a, b)

    首先,根据数论相关定理,该解一定存在,证明如下:

    a x + b y = G C D ( a ,   b ) = G C D ( b ,   a   m o d   b ) = b x + ( a   m o d   b ) y ax+by=GCD(a,\ b) = GCD(b,\ a\ mod\ b) = bx+(a\ mod\ b)y ax+by=GCD(a, b)=GCD(b, a mod b)=bx+(a mod b)y

    不妨设 a > b a > b a>b ,则 a = a / b ⋅ b + a   m o d   b    ( 被 除 数 = 商 × 除 数 + 余 数 ) a=a/b\cdot b + a\ mod\ b\ \ (被除数=商\times除数+余数) a=a/bb+a mod b  (=×+)

    所以 a x + b y = b x + ( a − a / b ⋅ b ) y = b x + a y − b ⋅ a / b ⋅ y = a y + b ( x − a / b ⋅ y ) ax+by=bx+(a-a/b\cdot b)y = bx+ay-b\cdot a/b\cdot y = ay +b(x-a/b\cdot y) ax+by=bx+(aa/bb)y=bx+ayba/by=ay+b(xa/by)

    由待定系数法,得到 { x = y ′ y = x ′ − a / b ⋅ y ′ \begin{cases} x &= y'\\ y &= x'-a/b\cdot y' \end{cases} {xy=y=xa/by

    其中 ( x ′ ,   y ′ ) (x',\ y') (x, y) 表示递归上一层的解, ( x ,   y ) (x,\ y) (x, y) 表示当前层的解

    a a a b b b 都在减小,当 b b b 减小到 0 时,就可以得到 x = 1 x=1 x=1 y = 0 y = 0 y=0 ,递归回去便可得到解。

    inline int exgcd(int a, int b, int& x, int& y) {
        if (b == 0) {
            x = 1, y = 0;
            return a;
        }
        int d = exgcd(b, a % b, x, y);
        int t = x;
        x = y, y = t - a/b * y; 
        return d;
    }
    
    struct node { 
        int x, y, z; 
    };
    inline node exgcd(int a, int b) {
        if (b == 0) return node(1, 0, a);
        node lat = exgcd(b, a % b);
        return node(lat.y, lat.x - a/b * lat.y, lat.z);
    }
    
  6. 求解线性同余方程

    定理1:对于方程 a x + b y = c ax+by=c ax+by=c ,该方程等价于 a x ≡ c   ( m o d   b ) ax \equiv c\ (mod\ b) axc (mod b) ,有整数解的充分必要条件是: c   m o d   G C D ( a ,   b ) = 0 c\ mod\ GCD(a,\ b) = 0 c mod GCD(a, b)=0

    定理2:若 G C D ( a ,   b ) = 1 GCD(a,\ b) = 1 GCD(a, b)=1 ,且 x 0 x_0 x0 y 0 y_0 y0 a x + b y = c ax+by=c ax+by=c 的一组解,则该方程的任一解可表示为: x = x 0 + b ⋅ t , y = y 0 − a ⋅ t x=x_0+b\cdot t,y=y_0-a\cdot t x=x0+bty=y0at ,且对任一整数 t t t ,皆成立。

    对于方程 a x + b y = c ax+by=c ax+by=c ,我们可以先用扩展欧几里得算法求出一组 x 0 ,   y 0 x_0,\ y_0 x0, y0 ,也就是 a x 0 + b y 0 = G C D ( a ,   b ) ax_0+by_0=GCD(a,\ b) ax0+by0=GCD(a, b) ,然后两边同时除以 G C D ( a ,   b ) GCD(a,\ b) GCD(a, b) ,再乘以 c c c 。这样就得到了方程 a ⋅ ( x 0 ⋅ c / G C D ( a ,   b ) ) + b ⋅ ( y 0 ⋅ c / G C D ( a ,   b ) ) = c a\cdot (x_0\cdot c/GCD(a,\ b)) + b\cdot(y_0\cdot c/GCD(a,\ b)) = c a(x0c/GCD(a, b))+b(y0c/GCD(a, b))=c

    而对于方程 a x + b y = c ax+by=c ax+by=c 的一个特解为: { x ′ = x 0 ⋅ c / G C D ( a ,   b ) y ′ = y 0 ⋅ c / G C D ( a ,   b ) \begin{cases} x'&=x_0\cdot c/GCD(a,\ b)\\y'&=y_0\cdot c/GCD(a,\ b) \end{cases} {xy=x0c/GCD(a, b)=y0c/GCD(a, b)

    通解为: { x = x ′ + b / G C D ( a ,   b ) ⋅ t y = y ′ − a / G C D ( a ,   b ) ⋅ t \begin{cases} x &= x'+b/GCD(a,\ b)\cdot t \\ y &= y'- a/GCD(a,\ b)\cdot t \end{cases} {xy=x+b/GCD(a, b)t=ya/GCD(a, b)t

    inline bool LinearEquation(int a, int b, int c, int&x, int& y) {
        int d = exgcd(a, b, x, y);
        if (d == 0 || c % d) return false; // 无解
        int k = c / d;
        x *= k, y *= k;  
        return true; // 有解
    }
    
1.4 逆元

a ∗ x ≡ 1   ( m o d   b ) a*x \equiv 1\ (mod\ b) ax1 (mod b) a a a b b b 互质,则称 x x x a a a 的逆元,记为 a − 1 a^{-1} a1

  1. 费马小定理求逆元:

    定理:如果 p p p 是一个质数,而整数 a a a 不是 p p p 的倍数,则有 a p − 1 ≡ 1   ( m o d   p ) a^{p-1} \equiv 1\ (mod\ p) ap11 (mod p)

    引理1:若 a a a b b b c c c 为任意3个整数,且 G C D ( m ,   c ) = 1 GCD(m,\ c) = 1 GCD(m, c)=1 ,则当 a ⋅ c ≡ b ⋅ c   ( m o d   m ) a\cdot c \equiv b\cdot c\ (mod\ m) acbc (mod m) 时,有 a ≡ b   ( m o d   m ) a\equiv b\ (mod\ m) ab (mod m)

    引理1证明:
    a ⋅ c ≡ b ⋅ c   ( m o d   m ) a ⋅ c − b ⋅ c ≡ 0 ( m o d   m ) ( a − b ) ⋅ c ≡ 0 ( m o d   m ) ( a − b ) ≡ 0 ( m o d   m ) ( 由 G C D ( m ,   c ) = 1 得 到 ) a ≡ b ( m o d   m ) \begin{aligned} a\cdot c &\equiv b\cdot c\ &(mod\ m)\\ a\cdot c - b\cdot c &\equiv 0 &(mod\ m)\\ (a-b)\cdot c &\equiv0 &(mod\ m)\\ (a-b) &\equiv 0 &(mod\ m) &(由GCD(m,\ c) = 1得到)\\ a &\equiv b &(mod\ m) \end{aligned} acacbc(ab)c(ab)abc 000b(mod m)(mod m)(mod m)(mod m)(mod m)(GCD(m, c)=1)

    引理2:设 m m m 是一个整数且 m > 1 m>1 m>1 b b b 是一个整数且 G C D ( m ,   b ) = 1 GCD(m,\ b) = 1 GCD(m, b)=1 。 如果 { a 1 ,   a 2 ,   …   ,   a m } \{a_1,\ a_2,\ …\ ,\ a_m\} {a1, a2,  , am} ( m o d   m ) (mod\ m) (mod m) 意义下的一个完全剩余系,则 { b ⋅ a 1 ,   b ⋅ a 2 ,   …   ,   b ⋅ a m } \{b\cdot a_1,\ b\cdot a_2,\ …\ ,\ b\cdot a_m\} {ba1, ba2,  , bam} 也是 ( m o d   m ) (mod\ m) (mod m) 意义下的一个完全剩余系。

    引理2证明:

    若存在2个整数 b ⋅ a i b\cdot a_i bai b ⋅ a j b\cdot a_j baj 在 $mod\ m $ 意义下同余 ( 1 ≤ i , j ≤ m ) (1 \le i ,j \le m) (1i,jm),即
    b ⋅ a i ≡ b ⋅ a j   ( m o d   m ) a i ≡ a j ( m o d   m ) \begin{aligned} b\cdot a_i &\equiv b\cdot a_j\ &(mod\ m) \\ a_i &\equiv a_j &(mod\ m) \end{aligned} baiaibaj aj(mod m)(mod m)

    因为 0 ≤ a i , a j ≤ m − 1 0\le a_i, a_j\le m-1 0ai,ajm1 a i ≠ a j a_i \not =a_j ai=aj ,矛盾。

    费马小定理证明:

    构造素数 p p p 的完全剩余系 P = { 1 ,   2 ,   3 ,   … ,   p − 1 } P=\{1,\ 2,\ 3,\ …,\ p-1 \} P={1, 2, 3, , p1}

    因为 G C D ( a ,   p ) = 1 GCD(a,\ p) = 1 GCD(a, p)=1 ,由引理2得 A = { a ,   2 a ,   3 a ,   … ,   ( p − 1 ) a } A=\{a,\ 2a,\ 3a,\ …,\ (p-1)a \} A={a, 2a, 3a, , (p1)a} 也是 p p p 的一个完全剩余系。

    由完全剩余系性质:
    1 × 2 × 3 × … × ( p − 1 ) ≡ a ⋅ 2 a ⋅ 3 a ⋅ … ⋅ ( p − 1 ) a ( m o d   p ) ( p − 1 ) ! ≡ ( p − 1 ) ! ⋅ a p − 1 ( m o d   p ) a p − 1 ≡ 1 ( m o d   p )   由 G C D ( ( p − 1 ) ! ,   p ) = 1 得 到 \begin{aligned} 1\times2\times 3\times …\times (p-1) &\equiv a\cdot 2a\cdot 3a\cdot …\cdot(p-1)a& (mod\ p)\\ (p-1)! &\equiv (p-1)!\cdot a^{p-1}& (mod\ p)\\ a^{p-1}&\equiv 1& (mod\ p) &\ 由GCD((p-1)!,\ p) = 1得到 \end{aligned} 1×2×3××(p1)(p1)!ap1a2a3a(p1)a(p1)!ap11(mod p)(mod p)(mod p) GCD((p1)!, p)=1

    ll fpow(ll base, ll power, ll mod) {
        ll res = 1;
        for (; power; power >>= 1, base = base*base % mod) 
            if (power & 1) res = res*base % mod;
        return res;
    }
    ll fermat_inv(ll a, ll n) {
        return fpow(a, n - 2, n);
    }
    
  2. 扩展欧几里得求逆元:

    裴蜀定理一个推论:

    对于方程 a x + b y = 1 ax+by=1 ax+by=1 ,只有当整数 a a a b b b 互质时,方程才有整数解。

    下面用反证法证明:设 a a a b b b 不互质,那么 a a a b b b 可以表示成 a = q ⋅ G C D ( a ,   b ) ,   b = p ⋅ G C D ( a ,   b ) a = q\cdot GCD(a,\ b),\ b = p\cdot GCD(a,\ b) a=qGCD(a, b), b=pGCD(a, b)

    带入上面的式子得到: q ⋅ G C D ( a ,   b ) ⋅ x + p ⋅ G C D ( a ,   b ) ⋅ y = 1 q\cdot GCD(a,\ b)\cdot x+p\cdot GCD(a,\ b)\cdot y = 1 qGCD(a, b)x+pGCD(a, b)y=1

    两边除以 G C D ( a ,   b ) GCD(a,\ b) GCD(a, b) ,得到 q x + p y = 1 G C D ( a ,   b ) qx+py=\frac{1}{GCD(a,\ b)} qx+py=GCD(a, b)1

    显然,当 a a a b b b 不互质时,等式的右边已经变成了小数,那么方程一定不存在整数解。

    故只有当整数 a a a b b b 互质时,该方程才有整数解

    ll exgcd_inv(ll a, ll n) {
        ll d, x, y;
        d = exgcd(a, n, x, y);
        return d == 1 ? (x + n) % n : -1;
    }
    
  3. 线性算法求逆元:

    首先, 1 − 1 ≡   1   ( m o d   p ) 1^{-1} \equiv \ 1\ (mod\ p) 11 1 (mod p)

    然后,我们设 p = k ∗ i + r ,   r < i ,   1 < i < p p=k*i+r,\ r<i,\ 1 < i < p p=ki+r, r<i, 1<i<p ,再将这个式子放到 m o d   p mod\ p mod p 意义下就会得到:

    k ∗ i + r ≡ 0   ( m o d   p ) ,    k = p / i ,    r = p   m o d   i k*i+r \equiv 0\ (mod\ p),\ \ k = p/i,\ \ r = p\ mod\ i ki+r0 (mod p),  k=p/i,  r=p mod i

    两边同时乘上 i − 1 ,   r − 1 i^{-1},\ r^{-1} i1, r1 就会得到:
    k ∗ r − 1 + i − 1 ≡ 0 ( m o d   p ) i − 1 ≡ − k ∗ r − 1 ( m o d   p ) i − 1 ≡ − p / i ∗ ( p   m o d   i ) − 1 ( m o d   p ) \begin{aligned} k*r^{-1}+i^{-1} &\equiv 0 &(mod\ p) \\ i^{-1} &\equiv -k*r^{-1} &(mod\ p) \\ i^{-1} &\equiv -p/i*(p\ mod\ i)^{-1} &(mod\ p) \end{aligned} kr1+i1i1i10kr1p/i(p mod i)1(mod p)(mod p)(mod p)

    ll Inv(int a, int P) {
        if (a == 1) return 1;
        return (P - P/a) * Inv(P%a, P);
    }
    
    inv[1] = 1;
    for (int i = 2; i < P; i ++)
    	inv[i] = (P - P/i) * inv[P%i] % P;
    
1.5 常用定理
  1. 整数的唯一分解定理:

    任意的正整数都有且只有一种方式写出其素因子的乘积表达式。 A = p 1 k 1 p 2 k 2 p 3 k 3 … p n k n A = p_1^{k_1}p_2^{k_2}p_3^{k_3}…p_n^{k_n} A=p1k1p2k2p3k3pnkn ,其中 p i p_i pi 均为素数。

    证明:我们将 ∀ n ∈ N \forall n\in \N nN 都分解一下,假设我们发现 N \N N 里面有一些数是分解不唯一的,那我们可以把它们都收集起来,形成集合 S S S ,那么显然有 S ⊂ N S\subset \N SN

    这里的 S ⊂ N S\subset N SN 说明我们可以找到一个最小的元素,设为 m m m 。既然 m m m 的分解不唯一,那么自然有 m = p 1 p 2 … p r = q 1 q 2 … q s m = p_1p_2…p_r=q_1q_2…q_s m=p1p2pr=q1q2qs ,这些 p ,   q p,\ q p, q 全是素数。

    然后可以重写一次 p ,   q p,\ q p, q ,让它们呈现: p 1 ≤ p 2 ≤ … ≤ p r p_1\le p_2\le … \le p_r p1p2pr q 1 ≤ q 2 ≤ … ≤ q s q_1\le q_2\le …\le q_s q1q2qs

    如果 p 1 = q 1 p_1=q_1 p1=q1 ,显然是会矛盾的,因为这样就会有一个数 n = p 2 p 3 … p r = q 2 q 3 … q s < m n = p_2p_3…p_r = q_2q_3…q_s< m n=p2p3pr=q2q3qs<m 是分解不唯一的,与 m m m 为分解不唯一的集合里最小矛盾。

    因此要么 p 1 < q 1 p_1<q_1 p1<q1 ,要么 q 1 < p 1 q_1<p_1 q1<p1 ,不妨设 p 1 < q 1 p_1<q_1 p1<q1

    我们构造一个整数 m ′ = m − p 1 q 2 … q s m' = m-p_1q_2…q_s m=mp1q2qs ,则有:
    m ′ = p 1 p 2 … p r − p 1 q 2 … q s = p 1   ( p 2 p 3 … p r − q 2 q 3 … q s ) ( 1 式 ) m ′ = q 1 q 2 … q s − p 1 q 2 … q s = ( q 1 − p 1 )   q 2 q 3 … q s ( 2 式 ) \begin{aligned} m' &= p_1p_2…p_r-p_1q_2…q_s = p_1\ (p_2p_3…p_r-q_2q_3…q_s)&(1式) \\ m' &= q_1q_2…q_s-p_1q_2…q_s = (q_1-p_1)\ q_2q_3…q_s&(2式) \end{aligned} mm=p1p2prp1q2qs=p1 (p2p3prq2q3qs)=q1q2qsp1q2qs=(q1p1) q2q3qs(1)(2)
    由于 p 1 < q 1 p_1<q_1 p1<q1 ,这导致了 0 < m ′ < m 0 < m' < m 0<m<m ,因此 m ′ m' m 的素数分解一定是唯一的(这是因为 m m m 已经是素数分解不唯一最小的数了,因此比 m m m 小的数只能分解唯一)。而依 (1式)知, p 1   ∣   m ′ p_1\ |\ m' p1  m ,再依(2式)知, p 1   ∣   q 1 − p 1 p_1\ |\ q_1-p_1 p1  q1p1 p 1   ∣   q 2 q 3 … q s p_1\ |\ q_2q_3…q_s p1  q2q3qs ,但是结合 p 1 < q 1 p_1<q_1 p1<q1 q 1 ≤ q 2 ≤ … ≤ q s q_1\le q_2\le … \le q_s q1q2qs 则知, p 1 p_1 p1 比这里的任何一个 q i q_i qi 都要小,而 q i q_i qi 又都是素数,因此 p 1 p_1 p1 不可能整除任何一个 q i q_i qi ,从而也就不可能整除 q 2 q 3 … q s q_2q_3 …q_s q2q3qs ,因此只可能是 p 1   ∣   q 1 − p 1 p_1\ |\ q_1-p_1 p1  q1p1

    p 1   ∣   q 1 − p 1 ⇔ ∃ k ∈ Z ,   k p 1 = q 1 − p 1 p_1\ |\ q_1-p_1 \Leftrightarrow \exist k \in \Z ,\ kp_1=q_1-p_1 p1  q1p1kZ, kp1=q1p1,也就是 p 1 ( k + 1 ) = q 1 p_1(k+1) = q_1 p1(k+1)=q1 ,从而说明 p 1   ∣   q 1 p_1\ |\ q_1 p1  q1 ,但是这两个都是素数,所以是不可能的。因此矛盾,得证。

    // 分解整数 A (A可能是质数也可能不是质数)
    int k = 0, A;
    int p[1001], n[1001]; 
    for (int i = 2; i * i <= A; ) {
        if (A % i == 0) {
            p[++ k] = i;
            n[k] = 0;
            while (A % i == 0) n[k] ++, A /= i;
        }
        if (i == 2) i ++; // 质数不会是偶数
        else i += 2;
    }
    if (A > 1) {   // 特殊判定:分解整数A (A为质数)
        p[++ k] = A;
        n[k] = 1;
    }
    
  2. 约数个数公式

    对于已经分解的整数 A = p 1 k 1 p 2 k 2 p 3 k 3 … p n k n A = p_1^{k_1}p_2^{k_2}p_3^{k_3}…p_n^{k_n} A=p1k1p2k2p3k3pnkn ,有 A 的所有因子个数为: T = ( 1 + k 1 ) ∗ ( 1 + k 2 ) ∗ … ∗ ( 1 + k n ) T=(1+k_1)*(1+k_2)*…*(1+k_n) T=(1+k1)(1+k2)(1+kn)

  3. 约数和公式

    对于已经分解的整数 A = p 1 k 1 p 2 k 2 p 3 k 3 … p n k n A = p_1^{k_1}p_2^{k_2}p_3^{k_3}…p_n^{k_n} A=p1k1p2k2p3k3pnkn ,有 A 的所有因子之和为: S = ( 1 + p 1 + p 1 2 + … + p 1 k 1 ) ∗ ( 1 + p 2 + p 2 2 + … + p 2 k 2 ) ∗ … ∗ ( 1 + p n + p n 2 + … + p n k n ) S=(1+p_1+p_1^2+…+p_1^{k_1})*(1+p_2+p_2^2+…+p_2^{k_2})*…*(1+p_n+p_n^2+…+p_n^{k_n}) S=(1+p1+p12++p1k1)(1+p2+p22++p2k2)(1+pn+pn2++pnkn)

    用递归二分求等比数列 1 + p + p 2 + … + p n 1+p+p^2+…+p^n 1+p+p2++pn

    (1)若 n n n 为奇数,一共有偶数项,则:
       1 + p + p 2 + … + p n =   ( 1 + p n / 2 + 1 )   +   p ⋅ ( 1 + p n / 2 + 1 ) + … + p n / 2 ⋅ ( 1 + p n / 2 + 1 ) =   ( 1 + p + p 2 + … + p n / 2 ) ⋅ ( 1 + p n / 2 + 1 ) \begin{aligned} &\ \ 1+p+p^2+…+p^n \\ = &\ (1+p^{n/2+1})\ +\ p\cdot (1+p^{n/2+1}) + … + p^{n/2}\cdot (1+p^{n/2+1})\\ = &\ (1+p+p^2+…+p^{n/2})\cdot (1+p^{n/2+1}) \end{aligned} ==  1+p+p2++pn (1+pn/2+1) + p(1+pn/2+1)++pn/2(1+pn/2+1) (1+p+p2++pn/2)(1+pn/2+1)
    (2)若 n n n 为偶数,一共有奇数项,则:
       1 + p + p 2 + … + p n =   ( 1 + p n / 2 + 1 )   +   p ⋅ ( 1 + p n / 2 + 1 ) + … + p n / 2 − 1 ⋅ ( 1 + p n / 2 + 1 ) + p n / 2 =   ( 1 + p + p 2 + … + p n / 2 − 1 ) ⋅ ( 1 + p n / 2 + 1 ) + p n / 2 \begin{aligned} &\ \ 1+p+p^2+…+p^n \\ = &\ (1+p^{n/2+1})\ +\ p\cdot (1+p^{n/2+1}) + … + p^{n/2-1}\cdot (1+p^{n/2+1})+p^{n/2}\\ = &\ (1+p+p^2+…+p^{n/2-1})\cdot (1+p^{n/2+1}) + p^{n/2} \end{aligned} ==  1+p+p2++pn (1+pn/2+1) + p(1+pn/2+1)++pn/21(1+pn/2+1)+pn/2 (1+p+p2++pn/21)(1+pn/2+1)+pn/2

    ll fpow(ll p, ll n) {
        ll res = 1;
        for (; n; n >>= 1, p = p*p)
            if (n & 1) res = res * p;
        return res;
    }
    ll sum(ll p, ll n) {  // 求 1 + p + p^2 + …… + p^n
        if (n == 0) return 1;
        if (n & 1) return sum(p, n/2) * (1 + fpow(p, n/2+1));
        return sum(p, n/2 - 1) * (1 + fpow(p, n/2 + 1)) + fpow(p, n/2);
    }
    
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值