数论学习笔记

概念不说了。

同余方程

同余方程基本形式:axc(mod b)ax\equiv c(\text{mod}\space b)

axc(mod b)yZ,s.t.ax+by=cax\equiv c(\text{mod}\space b)\Longleftrightarrow \exists y\in \mathbb{Z},s.t. ax+by=c

ax+by=cax+by=c 就可以用扩展欧几里得来求。

代码:

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

乘法逆元

ax1(mod p)ax\equiv 1(\text{mod}\space p),并且 (a,p)=1(a,p)=1,则称 aaxxmod p\text{mod}\space p 下互为逆元,x=inv(a)x=\text{inv}(a)

求解乘法逆元的方法:

  1. 扩欧,相当于 解 ax1(mod p)ax\equiv 1(\mod\space p)。适合求某一个数的逆元。
  2. 费马小定理,若 pp 是质数,且 (a,p)=1(a,p)=1,则 ap11(modp)a^{p-1}\equiv 1(\text{mod} p),那么 inv(a)=ap2\text{inv}(a)=a^{p-2}。适用于 pp 为质数的情况。
  3. 线性递推求逆元,适合求 1n1\sim n 的逆元。

设 p=aq+r,q=par=pmodaaq+r0(mod p)aqr(mod p)arinv(q)(mod p)inv(a)qinv(r)(mod p)那么 inv[a]=painv[pmoda]设\space p=aq+r,q=\bigg\lfloor\dfrac{p}{a}\bigg\rfloor,r=p\bmod a\\ \begin{aligned} aq+r&\equiv 0(\text{mod}\space p)\\ aq&\equiv -r(\text{mod}\space p)\\ a&\equiv -r\cdot \text{inv}(q)(\text{mod}\space p)\\ \text{inv}(a)&\equiv -q\cdot \text{inv}(r)(\text{mod}\space p)\\ \end{aligned}\\ 那么\space \text{inv}[a]=-\bigg\lfloor\dfrac{p}{a}\bigg\rfloor\cdot \text{inv}[p\bmod a]

总之,我觉得要求单个的逆元就用扩欧,多个的逆元就用线性递推,费马小定理随便。

中国剩余定理

这里直接讲扩展中国剩余定理。

定义:线性同余方程组,不要求模数两两互质。

{p1a1(mod m1)p2a2(mod m2)      pnan(mod mn)\begin{cases} p_1\equiv a_1(\text{mod}\space m_1)\\ p_2\equiv a_2(\text{mod}\space m_2)\\ \space\space\space\space\space \space\vdots\\ p_n\equiv a_n(\text{mod}\space m_n)\\ \end{cases}

就是求这个方程的一个解。

解法

采用数学归纳法。

  1. 假设前 k1k-1 个方程的特解为 xx,那么通解为 x+tMx+t\cdot M,其中 M=lcm(m1,m2,,mk1)M=\text{lcm}(m_1,m_2,\dots,m_{k-1})
  2. 求解 tt,使得 x+tMak(mod mk)x+t\cdot M\equiv a_k(\text{mod}\space m_k)
  3. exgcd 判断是否有解,若有解,则 xx+tMx\gets x+t\cdot 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
61
62
63
64
65
66
67
#include <bits/stdc++.h>
#define int long long

using namespace std;

const int kMaxN = 1e5 + 5;

int n, a[kMaxN], b[kMaxN];
int M = 1;
__int128 res, x, y;

__int128 mod (__int128 x, __int128 m) {
return (x % m + m) % m;
}

__int128 add (__int128 x, __int128 y, __int128 m) {
return (x + y >= m) ? (x + y - m) : (x + y);
}

__int128 times (__int128 x, __int128 y, __int128 m) {
return 1ll * x * y % m;
}

__int128 gcd (__int128 m, __int128 n) {
return (!n) ? m : gcd(n, m % n);
}

__int128 lcm (__int128 m, __int128 n) {
return m / gcd(m, n) * n;
}

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

__int128 inv (__int128 a, __int128 m) {
__int128 x, y;
exgcd(a, m, x, y);
return mod(x, m);
}

signed main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i] >> b[i];
}
res = b[1], M = a[1];
for (int i = 2; i <= n; ++i) {
__int128 s = mod(b[i] - mod(res, a[i]), a[i]);
__int128 d = exgcd(M, a[i], x, y);
__int128 m = M;
M = lcm(M, a[i]);
x = mod(times(x, s / d, a[i]), a[i]);
// cout << "***" << i << ' ' << res << endl;
res += times(x, m, M);
res = mod(res, M);
}
// cout << exgcd(4, 48, x, y) << endl;
cout << (long long)res << endl;
return 0;
}

欧拉函数

对于 nZ+n\in \mathbb{Z}^{+}φ(n)\varphi(n) 表示 1n1\sim n 中与 nn 互质的正整数个数。

  • 性质一:若 pp 是质数,φ(pn)=pn1(p1)\varphi(p^{n})=p^{n-1}\cdot(p-1)
  • 性质二:若 axa|xφ(ax)=aφ(x)\varphi(ax)=a\cdot\varphi(x)
  • 性质三:若 (a,b)=1(a,b)=1φ(ab)=φ(a)φ(b)\varphi(ab)=\varphi(a)\cdot \varphi(b)

公式:

If n=i=1kpiαi,then φ(n)=ni=1kpi1pi\text{If}\space n=\prod_{i=1}^{k}{p_i^{\alpha_i}}, \text{then}\space \varphi(n)=n\cdot\prod_{i=1}^{k}\dfrac{p_{i}-1}{p_{i}}

欧拉定理

(a,m)=1(a,m)=1aφ(m)1(mod m)a^{\varphi(m)}\equiv 1(\text{mod}\space m)

推论:ababmodφ(m)(mod m)a^b\equiv a^{b\bmod \varphi(m)}(\text{mod}\space m)

bφ(m)b\geq \varphi(m),则 ababmodφ(m)+φ(m)(mod m)a^b\equiv a^{b\bmod\varphi(m)+\varphi(m)}(\text{mod}\space m)


数论学习笔记
https://sobaliuziao.github.io/2022/01/28/post/7850e5e5.html
作者
Egg_laying_master
发布于
2022年1月28日
许可协议