数论学习笔记(约数篇二)

本文介绍欧拉函数、同余以及拓展欧几里得算法。

欧拉函数

定义

1 到 NN 中与 NN 互质的数的个数被称为欧拉函数,记为 φ(N)\varphi(N)

性质

显然,如果 NN 为质数,则 φ(N)=N1\varphi(N)=N-1

欧拉函数为 积性函数gcd(a,b)=1\gcd(a,b)=1,则 φ(ab)=φ(a)φ(b)\varphi(ab)=\varphi(a)\varphi(b)

n=pkn=p^{k}pp 为质数,则 φ(n)=n(11p)\varphi(n)=n(1-\dfrac{1}{p})

证明:
xxpkp^{k} 不互质,则有 pxp|x 成立。
xx 共有 np\dfrac{n}{p} 个,因此 φ(n)=nnp=n(11p)\varphi(n)=n-\dfrac{n}{p}=n(1-\dfrac{1}{p})

N=p_1c_1p_2c_2...p_mc_mN=p\_{1}^{c\_{1}}p\_{2}^{c\_{2}}...p\_{m}^{c\_{m}},则:
φ(N)=N×p_11p_1×p_21p_2×...×p_m1p_m\varphi(N)=N \times \dfrac{p\_{1}-1}{p\_{1}} \times \dfrac{p\_{2}-1}{p\_{2}} \times ... \times \dfrac{p\_{m}-1}{p\_{m}}
φ(N)=N×(11p_1)×(11p_2)×...×(11p_m)\varphi(N)=N \times \left ( 1-\dfrac{1}{p\_{1}} \right ) \times \left ( 1-\dfrac{1}{p\_{2}} \right ) \times ... \times \left ( 1-\dfrac{1}{p\_{m}} \right )
即:
${\small \varphi \left ( n \right ) = n \times \prod_{i=1}^{m} \left ( 1-\frac{1}{p_{i}} \right )} $

证明:φ\varphi 是积性函数。把 nn 拆成 p_ia_ip\_{i}^{a\_{i}} 的乘积形式可立即得证。

代码

我们只要在分解质因数时顺便将欧拉函数求出来就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int phi(int n) 
{
int ans = n;
for (int i = 2; i <= sqrt(n); i++)
{
if (n % i == 0)
{
ans = ans / i * (i - 1);
while (n % i == 0)n /= i;
}
}
if (n > 1)ans = ans / n * (n - 1);
return ans;
}

同余

定义

amodm=bmodma \bmod {m} = b \bmod {m} ,则称 aabb 同余,写作 ab(modm)a \equiv b \pmod{m}

同余类、剩余系

对于一个集合 {xx=a+km,a[0,m1],kZ}\{ x|x=a+km,a \in \left [ 0,m-1 \right ] , k \in Z \} 的所有数模 mm 同余,余数都是 aa 。该集合被称为一个模 mm同余类,简记为 ā
mm 的同余类一共 mm 个,它们构成 mm完全剩余系
1 到 mm 中与 mm 互质的数代表的同余类共有 φ(m)\varphi(m) 个,它们构成 mm简化剩余系

欧拉定理

若正整数 aann 互质,则 aφ(n)1(modn)a^{\varphi(n)} \equiv 1\pmod{n},其中 φ(n)\varphi(n) 为欧拉函数。

证明

S={a_1,a_2,...,a_φ(n)}S=\{ a\_{1},a\_{2},...,a\_{\varphi(n)} \}nn 的简化剩余系。
aann 互质。
a1(modn)\because a \equiv 1\pmod{n}aa_11(modn)aa\_{1} \equiv 1 \pmod{n}
aa_11(modn)\therefore aa\_{1} \equiv 1 \pmod{n}
同理,aa_2,aa_3,...,aa_φ(n)1(modn)aa\_{2},aa\_{3},...,aa\_{\varphi(n)}\equiv 1 \pmod{n}
aa_1×aa_2×...×aa_φ(n)1(modn)\therefore aa\_{1} \times aa\_{2} \times...\times aa\_{\varphi(n)}\equiv1\pmod{n}
aφ(n)(a_1a_2...a_φ(n))a_1a_2...a_φ(n)(modn)\therefore a^{\varphi(n)}\left ( a\_{1}a\_{2}...a\_{\varphi(n)} \right )\equiv a\_{1}a\_{2}...a\_{\varphi(n)} \pmod{n}
aφ(n)1(modn)\therefore a^{\varphi(n)}\equiv 1 \pmod{n}

费马小定理

pp 为质数,则对于任意整数 aa,有 apa(modp)a^{p}\equiv a \pmod{p},即 ap11(modp)a^{p-1}\equiv 1\pmod{p}
证明太简单了,懒得证(用欧拉函数和欧拉定理证)

扩展欧几里得算法

贝祖定理(裴蜀定理)

定义

对于任意整数 aabb,存在一对整数 xxyy,满足 ax+by=gcd(a,b)\mathbf{ax + by = \gcd(a,b)}。特别地,一定存在 xxyy 满足 ax+by=dax + by = d
等价的表述:不定方程 ax+by=cax + by = caabbcc 为整数)有解的充要条件为 gcd(a,b)c\gcd(a,b)| c
推论:aabb 互质等价于 ax+by=1ax + by = 1 有解

原理

考虑如何求得 ax+by=dax + by = d 的一个解。这里 d=gcd(a,b)d = \gcd(a,b)

考虑使用欧几里德算法的思想,令 a=bq+ra = bq + r,其中 r=amodbr= a \bmod b;递归求出 bx+ry=dbx + ry = d 的一个解。

设求出 bx+ry=dbx + ry = d 的一个解为 x=x_0x = x\_{0}y=y_0y = y\_{0},考虑如何把它变形成 ax+by=dax + by = d 的解。

a=bq+ra = bq + r 代入 ax+by=dax + by = d、化简得 b(xq+y)+rx=db(xq + y)+ rx = d

我们令 xq+y=x_0xq + y = x\_{0}x=y_0x = y\_{0},则上式成立

x=y_0x=y\_{0}y=x_0y_0qy=x\_{0}-y\_{0}qax+by=dax + by = d 的解

边界情况:b=0b = 0 时,令 x=1x = 1y=0y = 0

代码

1
2
3
4
5
6
7
8
9
10
11
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;
}

求出 ax + by = c 的所有解

先用 exgcd 求出任意一个解 x_0x\_{0}y_0y\_{0}
ax_0+by_0=cax\_{0}+by\_{0}=c
再求出 ax+by=0ax + by = 0 的最小(绝对值)解 x=bgcd(a,b)x' = \dfrac{b}{\gcd(a,b)}y=agcd(a,b)y' = \dfrac{-a}{\gcd(a,b)}
(ax_0+by_0)+k(ax+by)=c(ax\_{0}+by\_{0})+k(ax'+by')=c
a(x_0+kx)+b(y_0+ky)=ca(x\_{0}+kx')+b(y\_{0}+ky')=c
所有解就是 x=x_0+kxx=x\_{0}+kx'y=y_0+kyy=y\_{0}+ky'kZk \in Z

乘法逆元

若整数 b,m 互质,并且 ba\mathbf{b|a},则存在一个整数 xx,使得 aba×x(modm)\mathbf{\dfrac{a}{b}\equiv a \times x\pmod{m}}
xxbb 的模 mm 乘法逆元,记为 b1(modm)b^{-1} \pmod{m}
可以推得:mm 为质数时,bm2b^{m-2} 即为 bb 的乘法逆元(即 xx )。
那么咋求逆元捏?

快速幂求逆元

快速幂

快速幂是啥?
可以看成是二进制优化的用来求 abmodp\mathbf{a^{b}\bmod p} 的东西。

代码

求逆元相当于求 bp2modpb^{p-2}\bmod p,所以能用快速幂求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#include<cstdio>
#include<algorithm>
#define int unsigned long long
using namespace std;
const int N = 3000101;
int n, m;
inline int qm(int a, int k, int p)
{
int ans = 1;
while (k)
{
if (k & 1)ans = ans * a % p;
k >>= 1;
a = a * a % p;
}
return ans;
}
signed main() {
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; i++) printf("%lld\n", qm(i, m - 2, m));
return 0;
}

扩展欧几里得算法(贝祖定理)求逆元

求逆元又等价于求 ax+by=1ax + by = 1
所以可以直接上板子。

代码

1
2
3
4
5
6
int inv(int a, int b) 
{
int x, y;
exgcd(a, b, x, y);
return x;
}

线性求逆元

在求 ii 的逆元时,

p=pi×i+pmodi\because p=\left \lfloor \dfrac{p}{i} \right \rfloor \times i+p \bmod i(⌊ ⌋为向下取整),

a=pia = \left \lfloor \dfrac{p}{i} \right \rfloorb=pmodib = p \bmod i

p=a×i+b\therefore p=a \times i+b

a×i+b=p\because a \times i+b=p

a×i+b=0(modp)\therefore a\times i+b=0 \pmod{p}

a×i=b(modp)\therefore a\times i=-b \pmod{p}

i=ba(modp)\therefore i=-\dfrac{b}{a} \pmod{p}

i1=ab(modp)\therefore i^{-1}=- \dfrac{a}{b}\pmod{p}

综上,ii 的逆元为 pi×ipmodi\dfrac{-\left \lfloor \dfrac{p}{i} \right \rfloor\times i}{p \bmod i}

inv[i]inv[ i ]ii 的逆元,

i1=ab(modp)\because i^{-1}=-\dfrac{a}{b}\pmod{p}

inv[i]=a×b1(modp)\therefore inv[i]=-a\times b^{-1}\pmod{p}

b1=inv[b]\because b^{-1}=inv[b]

inv[i]=ainv[b](modp)\therefore inv[i]=-\dfrac{a}{inv[b]}\pmod{p}

inv[i]=piinv[pmodi](modp)\therefore inv[i]=-\dfrac{\left \lfloor \dfrac{p}{i} \right \rfloor}{inv[p\bmod i]}\pmod{p}

inv[i]=ppiinv[pmodi]modp(xmodp=(x+p)modp)\therefore inv[i]=\dfrac{p-\left \lfloor \dfrac{p}{i} \right \rfloor}{inv[p\bmod i]\bmod p}(\because x\bmod p=(x+p)\mod p)

有了公式后就能用线性的复杂度求出每个数的逆元了。

代码

1
2
for (inv[1] = 1, i = 2; i <= n; ++i)
inv[i] = (p - p / i) * inv[p % i] % p;

线性同余方程

形如 axc(modm)ax ≡ c\pmod{m} 的方程(关于 xx),称为线性同余方程。
该方程等价于 ax+my=cax + my = c,有解条件为 gcd(a,m)c\gcd(a,m)| c
所以可以用 拓展gcd\gcd 来求。
求出 x_0x\_{0}y_0y\_{0},满足 ax_0+my_0=gcd(a,m)ax\_{0}+my\_{0}=\gcd(a,m)
然后 x=x_0×bgcd(a,m)x=x\_{0}\times\dfrac{b}{\gcd(a,m)}
xx 即为解。

剩下的下次再说吧。