红魔咖啡馆

头发越掉越多,头发越掉越少

0%

【数学】数论基础

整除

定义与性质

\(a,b\in \Z,a\neq0\),若\(\exists q\in \Z\),使得\(b=aq\),那么说b可被a整除,记作\(a|b\)

  • \(a\mid b \iff -a\mid b \iff a\mid -b \iff |a|\mid |b|\)
  • \(a\mid b \wedge b\mid c \implies a\mid c\)
  • \(a\mid b \wedge a\mid c \iff \forall x,y\in\mathbb{Z},\;a\mid(xb+yc)\)
  • \(a\mid b \wedge b\mid a \implies b=\pm a\)
  • \(m\neq0\),那么
    \[ a\mid b \iff ma\mid mb \]
  • \(b\neq0\),那么
    \[ a\mid b \implies |a|\le|b| \]
  • \(a\neq0,\;b=qa+c\),那么
    \[ a\mid b \iff a\mid c \]

约数

定义:若\(a|b\),则\(b\)\(a\)的倍数,\(a\)\(b\)的约数

性质:

  • 0是所有非0正数的倍数,对于整数\(b \neq a\),b的约数只有有限个

  • 平凡约数:对于整数\(b\neq 0\),±1、±b是b的平凡约数

    \(b=±1\)时,只有两个平凡约数

  • 真约数:b的其他约数

    • \(b\neq 0\),当d遍历b的全体约数时,\(\frac{b}{d}\)也遍历b的全体约数
    • \(b>0\),则当d遍历b时全体正约数时,\(\frac{b}{d}\)也遍历b的全体约数

没有特殊说明,约数总是指向正约数

余数

余数

\(a,b\)为两个给定的整数,\(a\neq0\). 设\(d\)是一个给定的整数,则一定存在唯一一对整数\(q\)\(r\),满足\(b=qa+r\)\(q=\lfloor\frac{b}{a} \rfloor ,d\leq r<|a|+d\)

其中这里的d表示不同取值区间的余数,无论整数d取何值,r统称余数,\(a|b\)等价于\(a|r\)

带余数除法

一般情况下,\(d=0\),此时\(b=qa+r\)\(0\leq r<|a|\)称为带余数除法,余数r称为最小非负余数,如果没有特别说明,余数总是指最小非负余数

r可以写成\(r=b\bmod{a}\)

余数的性质

  • 任一整数被正整数a除后,余数一定是且仅是0到(a-1)这a个数中的一个
  • 相邻的a个整数被正整数a除后,恰好取到上述a个余数,特别的,一定有且仅有一个数被a整除

最大公约数与最小公倍数

最大公约数

定义

一组整数的公约数,是指同时是这组数中每一个数的约数的数。\(\pm 1\) 是任意一组整数的公约数。一组整数的最大公约数,是指所有公约数里面最大的一个。写作gcd(a,b)

性质

  • \(\displaystyle \gcd(a_1,\dots,a_n)=\gcd\bigl(|a_1|,\dots,|a_n|\bigr)\)

  • \(\displaystyle \gcd(a,b)=\gcd(b,a)\)

  • \(a\neq0\),则 \[\gcd(a,0)=\gcd(a,a)=|a|.\]

  • \(\displaystyle \gcd(bq+r,\;b)=\gcd(r,\;b)\)

  • \(\displaystyle \gcd(a_1,\dots,a_n) =\gcd\bigl(\gcd(a_1,a_2),a_3,\dots,a_n\bigr).\)
    进而对任意 \(1<k<n\),都有
    \[ \gcd(a_1,\dots,a_n) =\gcd\!\bigl(\gcd(a_1,\dots,a_k)\,,\,\gcd(a_{k+1},\dots,a_n)\bigr). \]

  • 对不全为 0 的整数 \(a_1,\dots,a_n\) 和非零整数 \(m\)
    \[ \gcd(m a_1,\dots,m a_n) =|m|\;\gcd(a_1,\dots,a_n). \]

  • 对不全为 0 的整数 \(a_1,\dots,a_n\),若 \(\gcd(a_1,\dots,a_n)=d\),则
    \[ \gcd\bigl(a_1/d,\dots,a_n/d\bigr)=1. \]

  • \(\displaystyle \gcd\bigl(a^n,b^n\bigr)=\bigl(\gcd(a,b)\bigr)^n.\)

  • \(b\mid ac\)\(\gcd(a,b)=1\),则 \(b\mid c.\)

  • \(b\mid c,\;a\mid c\)\(\gcd(a,b)=1\),则 \(ab\mid c.\)

  • \(\gcd(a,b)=1\),则 \(\gcd(a,bc)=\gcd(a,c).\)

  • \(\gcd(a_i,b_j)=1,\;\forall\,1\le i\le n,\;1\le j\le m\),则
    \[ \gcd\Bigl(\prod_{i=1}^n a_i\,,\,\prod_{j=1}^m b_j\Bigr)=1. \] 特别地,若 \(\gcd(a,b)=1\),则
    \[ \gcd(a^n,b^m)=1. \]

  • 对整数 \(a_1,\dots,a_n\),若存在 \(v\in\mathbb{Z}\) 使
    \[ \prod_{i=1}^n a_i = v^m, \] 且对任意 \(i\neq j\)\(\gcd(a_i,a_j)=1\),则
    \[ \forall\,1\le i\le n,\quad \sqrt[m]{a_i}\in\mathbb{Z}_0. \]

求法

欧几里得算法

对于正整数\(a,b\),有\(\gcd(a,b)=\gcd(b, a\bmod{b})\)

代码实现如下:

递归版

1
2
3
ll gcd(ll a,ll b){
	return b==0?a:gcd(b,a%b);
}

位运算版

1
2
3
4
ll gcd(ll a,ll b){
	while(b^=a^=b^=a%=b);
	return a;
}

多个数求gcd,答案一定是每个数的约数,那么也一定是每相邻两个数的约数。我们采用归纳法,可以证明,每次取出两个数求出答案后再放回去,不会对所需要的答案造成影响。

扩展欧几里得算法

exgcd是用来求形如\(ax+by=\gcd(a,b)\)的一组可行解的算法

证明略,一组可行解形如\(x_1=y_2,y_1=x_2-\lfloor\frac{a}{b} \rfloor y_2\)

\(b=0\)时,显然有\(\gcd(a,0)=a\),则一组解为\(x=1, y=0\)

代码:

1
2
3
4
5
6
7
8
9
10
11
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1; y=0;
		return a;
	}
	ll d=exgcd(b,a%b,x,y);
	ll t=x;
	x=y;
	y=t-(a/b)*y;
	return d;
}

更相减损术

这个方法出自九章算术:

  1. 任意给定两个正整数,判断是否都是偶数,若是,则用2约分,若不是,则执行下一步
  2. 用较大的数减较小的数,接着将所得差与减数比较,并以大数减小数,操作至所得减数和差相等为止,则该等数就是所求的最大公因数

互素

\(\gcd(a_1,b_1)=1\),称\(a_1,a_2\)互素,若\(\gcd(a_1,\cdots,a_n)=1\)\(a_1,\cdots,a_n\)互素

多个整数互素,不一定两两互素

快速GCD

预处理

\(O(n)\)预处理,\(O(1)\)查询两个小于\(n\)的数的快速gcd

预处理:

  • 预处理所有\((i,j)\),其中\(i,j\leq\sqrt{n}\)的gcd,可以以\(O(n)\)推出
  • 预处理\(n\)以内质数

查询:

\(x=abc\),则\((x,y)=(a,y)\times\left(b,\dfrac{y}{(a,y)}\right)\times\left(c,\dfrac{y}{(ab,y)}\right)\)

\(a\in P\),只需要判断\(a\)是否整除\(y\),否则\((a,y)=(y\bmod a, a)\),因为\(a\leq \sqrt{n}\),可查表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const int T = 1000;
const int M = 1000000;

int g[T][T], fac[M][3];
bitset<M> vis;
vector<int> pri;
void prework() {
  vis[0] = vis[1] = true;
  fac[1][0] = fac[1][1] = fac[1][2] = 1;
  for (int i = 2; i < M; ++i) {
    if (!vis[i]) {
      fac[i][0] = fac[i][1] = 1;
      fac[i][2] = i;
      pri.push_back(i);
    }
    for (int j : pri) {
      int mul = i * j;
      vis[mul] = true;
      fac[mul][0] = fac[i][0] * j;
      fac[mul][1] = fac[i][1];
      fac[mul][2] = fac[i][2];
      sort(fac[mul], fac[mul] + 3);
      if (i % j == 0)
        break;
    }
  }
  for (int i = 0; i < T; ++i)
    g[0][i] = g[i][0] = i;
  for (int i = 1; i < T; ++i)
    for (int j = 1; j <= i; ++j)
      g[i][j] = g[j][i] = g[j][i % j];
}
int gcd(int a, int b) {
  int ans = 1;
  for (int i = 0; i < 3; ++i) {
    int _ = fac[a][i] > T ? (b % fac[a][i] ? 1 : fac[a][i])
                          : g[fac[a][i]][b % fac[a][i]];
    b /= _;
    ans *= _;
  }
  return ans;
}

更相减损术

\(O(\log{n})\)

  • \(a=b\), \((a,b)=a=b\)
  • \(2|a,2|b\), \((a,b)=\left(\dfrac{a}{2},\dfrac{b}{2}\right)\)
  • \(2\mid a,2\nmid b\), \((a,b)=\left(\dfrac{a}{2},b\right)\)
  • 若均不满足,设\(a>b\), 则\((a,b)=(a-b,b)\)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int gcd(int a, int b) {
  int i = __builtin_ctz(a);
  int j = __builtin_ctz(b);
  int k = min(i, j);
  int d;
  b >>= j;
  while (a) {
    a >>= i;
    d = b - a;
    i = __builtin_ctz(d);
    if (a < b) b = a;
    if (d < 0) a = -d;
    else a = d;
  }
  return b << k;
}

最小公倍数

定义

一组整数的公倍数,是指同时是这组数中每一个数的倍数的数。0是任意一组整数的公倍数。

一组整数的最小公倍数,是指所有正的公倍数里面,最小的一个数。记作lcm(a,b)

性质

  • \(\displaystyle lcm(a_1,\dots,a_n)=lcm(|a_1|,\dots,|a_n|)\)

  • \(\displaystyle lcm(a,b)=lcm(b,a)\)

  • \(a\neq0\),则 \(lcm(a,1)=lcm(a,a)=|a|.\)

  • \(a\mid b\),则 \(lcm(a,b)=|b|.\)

  • \(\displaystyle lcm(a_1,\dots,a_n) =lcm\bigl(lcm(a_1,a_2),a_3,\dots,a_n\bigr).\)
    进而对任意 \(1<k<n-1\),都有
    \[ lcm(a_1,\dots,a_n) =lcm\Bigl(lcm(a_1,\dots,a_k),\;lcm(a_{k+1},\dots,a_n)\Bigr). \]

  • \(a_i\mid m,\ \forall\,1\le i\le n\),则
    \[ lcm(a_1,\dots,a_n)\mid m. \]

  • \(\displaystyle lcm(ma_1,\dots,ma_n)=|m|\;lcm(a_1,\dots,a_n)\,.\)

  • \(\displaystyle lcm(a,b,c)\,lcm(ab,bc,ca) =lcm(a,b)\,lcm(b,c)\,lcm(c,a)\,.\)

  • \(\displaystyle lcm(a^n,b^n)=\bigl(lcm(a,b)\bigr)^n\,.\)

求法

两个数:\(\gcd(a,b)\times lcm(a,b)=a\times b\)

代码

1
2
3
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b; // 防止 a*b 爆 ll,所以先 /gcd 再 *b
}

多个数:我们其实没有必要求一个共同的最大公约数再去处理,最直接的方法就是,当我们算出两个数的 gcd,或许在求多个数的 gcd时候,我们将它放入序列对后面的数继续求解,那么,我们转换一下,直接将最小公倍数放入序列即可。

素数与合数

质数

算术基本定理

内容

算术基本引理:设p是素数,\(p|a_1a_2\),那么\(p|a_1\)\(p|a_2\)至少有一个成立

唯一分解定理:设正整数a,则必有表示\(a=p_1p_2\cdots p_s\),其中\(p_j(1\leq j\leq s)\)是素数,且不计次序的意义下,该表示唯一

素数的另一种定义

对整数\(p\ne0,\pm1\),若对任意满足\(p|a_1a_2\)的整数\(a_1,a_2\)均有\(p|a_1\)\(p|a_2\)成立,则称p是素数

同余

定义

\(m\ne0\)。若\(m\mid(a-b)\),称m为模数,当 $xm=y m $时,我们说 xy 关于 m 同余,表示为 \(x≡y(\bmod m)\),这种表示称为模m的同余式

性质

  • 定理 1\[a \equiv b \pmod m\]\[d \mid m\] 时,有 \[a \equiv b \pmod d.\]

  • 定理 2\[a \equiv b \pmod m\quad\text{且}\quad c \equiv d \pmod m\] 时,有

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
      a + c \equiv b + d \pmod m,\\
      a - c \equiv b - d \pmod m,\\
      a \times c \equiv b \times d \pmod m.
    
    - **定理 3**  当  $$ac \equiv bd \pmod m\quad\text{且}\quad \gcd(c,m)=1$$  时,有  $$a \equiv b \pmod m.$$
      
    - **定理 4**  当  $$a \equiv b \pmod m$$  时,对于任意的 $c\neq0$,有  $$ac \equiv bc \pmod m.$$
      
    - **定理 5**  当  $$a \equiv b \pmod m$$  时,对于任意的 $k>0$,有  $$a^k \equiv b^k \pmod m.$$
      
    - **定理 6**  当  $$a \equiv b \pmod m$$  时,对于任意的整数 $t$,有  $$a = b + t\,m.$$
    
    ## 同余原理
    
    当需要返回数据很大,超过了longlong的范围,一般需要返回一个数字对另一个数字取模的结果
    
    
    
    对于四则运算,位数(bits)固定,我们认为时间复杂度为$O(1)$,但保留中间结果的情况下,位数可能会改变,导致复杂度增加
    
    **定理:对于k位(非32、64位)整数,加减的复杂度为$O(k)$,乘除的复杂度变为$O(k^2)$**
    
    此时需要同余原理
    
    同余的数学化表示:
    
    ### 加法同余
    
    对于$(a+b)\bmod{k}=c$,为了避免$a+b$得到更大的位数以出现问题,我们可以分别对$a$和$b$取模再相加取模,即$(a\bmod{k}+b\bmod{k})\bmod{k}=c'$,这样可以把$a$和$b$限制在32或64位,结果$c=c'$
    
    
    
    ### 乘法同余
    
    对于$(a\times b)\bmod{k}=c$,分别对$a$和$b$取模再相乘取模,即$(a\bmod{k}\times b\bmod{k})\bmod{k}=c'$,这样可以把$a$和$b$限制在32或64位,结果$c=c'$
    
    **注意:要保证相乘时中间结果不能溢出**
    
    
    
    ### 减法同余
    
    关于取模,若一个数取模后的结果是负数,**则需要加一个模数后取模**,以获得他的正数表示
    
    例如一个数%7的结果是-2,等同于这个数+7后%7的结果5,因为两者加2后分别是0和7,都可以被7整除
    
    对于$(a-b)\bmod{k}=c$,我们需要在分别模m的基础上加一个m,即$((a\bmod{k}-b\bmod{k})+m)\bmod{k}=c'$,为了避免获得负数中间结果
    
    # C/C++的整数除法与取模
    
    ## 规定
    
    C/C++规定在整数除法中:
    
    - 除数为0时,行为未定义
    - 否则$\frac{a}{b}\times b+a\% b=a$
    
    即取模运算的符号取决于除法如何取整,而这是实现定义的
    
    从C++11起,规定**商向零取整**,取模的符号**与被除数相同**

    5 % 3 == 2; 5 % -3 == 2; -5 % 3 == -2; -5 % -3 == -2;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    ## 快速乘
    
    要求模数在long long范围内的乘法取模,避免整数溢出,可以使用快速乘,能够实现$O(1)$且不需要`int128`
    
    我们可以发现:$a\times b\bmod{m}=a\times b-\lfloor\frac{ab}{m}\rfloor\times m$
    
    使用ull的自然溢出,可得:$a\times b\bmod{m}=a\times b-\lfloor\frac{ab}{m}\rfloor\times m=(a\times b-\lfloor\frac{ab}{m}\rfloor\times m)\bmod{2^{64}}$
    
    对于$\lfloor\frac{ab}{m}\rfloor$,若结果r在$[0,m)$时,直接返回r,否则返回$r+m$
    
    
    
    ```c++
    long long binmul(long long a, long long b, long long m) {
      unsigned long long c =
          (unsigned long long)a * b -
          (unsigned long long)((long double)a / m * b + 0.5L) * m;
      if (c < m) return c;
      return c + m;
    }

数论函数

数论函数指定义域为正整数的函数,可以视为一个数列

积性函数

定义

  • 数论中,若函数\(f(n)\)满足\(f(1)=1\),且\(f(xy)=f(x)f(y)\)对任意互质的\(x,y\in \N^*\)都成立,则\(f(n)\)为积性函数
  • 数论中,若函数\(f(n)\)满足\(f(1)=1\),且\(f(xy)=f(x)f(y)\)对任意的\(x,y\in \N^*\)都成立,则\(f(n)\)为完全积性函数

性质

\(f(x)\)\(g(x)\) 均为积性函数,则以下函数也为积性函数:

  • \(h(x)=f(x^p)\)
  • \(h(x)=f^p(x)\)
  • \(h(x)=f(x)\,g(x)\)
  • \[h(x)=\sum_{d\mid x}f(d)\,g\Bigl(\frac{x}{d}\Bigr)\]

对正整数 \(x\),设其唯一质因数分解为
\[ x=\prod_i p_i^{k_i}\,, \] 其中 \(p_i\) 为质数,\(k_i\) 为正整数。

  • \(F(x)\) 为积性函数,则
    \[ F(x)=\prod_i F\bigl(p_i^{k_i}\bigr)\,. \]

  • \(F(x)\) 为完全积性函数,则
    $$ F(x)=_i F(p_i^{k_i}) =_i^{k_i},.

    $$

加性函数

定义

  • 数论中,若函数\(f(n)\)满足\(f(1)=1\),且\(f(xy)=f(x)+f(y)\)对任意互质的\(x,y\in \N^*\)都成立,则\(f(n)\)为积性函数
  • 数论中,若函数\(f(n)\)满足\(f(1)=1\),且\(f(xy)=f(x)+f(y)\)对任意的\(x,y\in \N^*\)都成立,则\(f(n)\)为完全积性函数

性质

对正整数 \(x\),设其唯一质因数分解为
\[ x = \prod_i p_i^{k_i}, \] 其中 \(p_i\) 为质数,\(k_i\) 为正整数。

  • \(F(x)\)加性函数,则有
    \[ F(x) = \sum_i F\bigl(p_i^{k_i}\bigr)\,. \]

  • \(F(x)\)完全加性函数,则有
    \[ F(x) = \sum_i F\bigl(p_i^{k_i}\bigr) = \sum_i F(p_i)\,\cdot k_i\,. \]