你也想和我一样口算 1030 mod 11 吗?

全文 1.6 万余字。推荐学时:4学时 阅读全文可能需要20分钟甚至更长时间。

文章目录

  • 素数计数函数的估计值
  • 斐波那契数列
    • 通项公式
    • 常用性质
  • 矩阵快速幂
  • 辗转相除法
    • 实现
    • 效率
    • 应用
  • 最大公约数的性质
  • 素数筛
  • 埃拉托瑟尼筛
    • 实现
    • 效率
  • 积性函数
  • 欧拉函数
    • 常用性质
  • 欧拉反演
    • 证明
  • 欧拉筛
    • 实现
    • 效率
    • 原理和应用
    • 生成积性函数的函数值表
  • 欧拉定理
    • 推论
  • 贝祖定理
    • 证明
    • 推论
  • 扩展辗转相除法
    • 推导
    • 实现
    • 解空间
  • 线性同余方程
    • 线性同余方程有解的充要条件是 b 为 gcd(a,n) 的整数倍
    • 求解
  • 模逆元
    • 整数 a a a 对模数 m m m 有模逆元的充要条件是 a , m a,m a,m 互质
    • 利用欧拉定理求模逆元
    • 利用扩展辗转相除法求模逆元
  • 孙子定理

素数计数函数的估计值

为什么我们要研究质数?因为几乎所有正整数都可以由若干个质数相乘来生成,可以认为质数是正整数的基本成分。这就是为什么它叫“质数”或者“素数”。

π ( x ) ≈ x ln ⁡ x \pi\left(x\right)\approx \frac{x}{\ln{x}} π(x)lnxx

对于正数 x , x, x, π ( x ) \pi\left(x\right) π(x)素数计数函数(Prime-counting function),即不超过 x x x 的素数的数目。当 x x x 较小时( x < 1 0 5 x<10^{5} x<105),这个估计的误差较大。上述估计值总是比实际值小,所以在设定素数表的大小时,我们通常会给估计值乘上 1.2 1.2 1.2 进行修正,防止空间不足。

素数计数函数有更为准确的估计,但上面的是最好算的。

斐波那契数列

Fibonacci sequence。仅在这一节中,我们约定 F i F_{i} Fi 表示第 i i i 个斐波那契数,则 F 1 = F 2 = 1. F_{1} = F_{2} = 1. F1=F2=1.

( 0 , )    1 ,   1 ,   2 ,   3 ,   5 ,   8 ,   13 ,   21 ,   34 , ⋯ (0,)\;1,\,1,\,2,\,3,\,5,\,8,\,13,\,21,\,34,\cdots (0,)1,1,2,3,5,8,13,21,34,

通项公式

由递推公式及初值,可以得出,当 n > 0 n>0 n>0

F n = 1 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] = φ n 5 − ( 1 − φ ) n 5 . F_{n} = \frac{1}{\sqrt{5}} \left[ \left( \frac{1+\sqrt{5}}{2} \right)^{n} - \left( \frac{1-\sqrt{5}}{2} \right) ^{n}\right]= \frac{\varphi^{n}}{\sqrt{5}} - \frac{\left(1-\varphi\right)^{n}}{\sqrt{5}} . Fn=5 1[(21+5 )n(215 )n]=5 φn5 (1φ)n.

常用性质

  • F n = O ( φ n ) ,    log ⁡ F n = O ( n ) F_n=\Omicron(\varphi^{n}),\;\log{F_n}=\Omicron(n) Fn=O(φn),logFn=O(n)

  • 随着 n n n 的增大, F n + 1 / F n F_{n+1}/F_{n} Fn+1/Fn 越来越接近于黄金比例 ( 5 + 1 ) / 2 (\sqrt{5}+1)/2 (5 +1)/2

  • 三个连续的斐波那契数两两互质,因为

gcd ⁡ ( F i + 2 , F i + 1 ) = gcd ⁡ ( F i + 2 − F i + 1 , F i + 1 ) = gcd ⁡ ( F i , F i + 1 ) \gcd\left(F_{i+2},F_{i+1}\right)=\gcd\left(F_{i+2}-F_{i+1},F_{i+1}\right)=\gcd\left(F_{i},F_{i+1}\right) gcd(Fi+2,Fi+1)=gcd(Fi+2Fi+1,Fi+1)=gcd(Fi,Fi+1)

gcd ⁡ ( F 2 , F 1 ) = 1.      ■ \gcd\left(F_{2},F_{1}\right)=1.\;\; \texttt{■} gcd(F2,F1)=1.

  • n n n 个斐波那契数的和为 F n + 2 − 1 F_{n+2}-1 Fn+21

  • n ≥ 3 n\ge 3 n3 时, F n F_{n} Fn 能整除 F m F_{m} Fm 的充要条件是 n n n 能整除 m m m

  • gcd ⁡ ( F m , F n ) = F gcd ⁡ ( m , n ) \gcd(F_{m},F_{n})=F_{\gcd(m,n)} gcd(Fm,Fn)=Fgcd(m,n)

  • F n − 1 F n + 1 − F n 2 = ( − 1 ) n F_{n-1}F_{n+1}-F_{n}^{2}=(-1)^{n} Fn1Fn+1Fn2=(1)n

矩阵快速幂

注意到递推式 f ( n ) = a f ( n − 1 ) + b f ( n − 2 ) f(n) = af(n-1)+bf(n-2) f(n)=af(n1)+bf(n2) 可以写成矩阵的形式

[ a b 1 0 ] [ f ( n − 1 ) f ( n − 2 ) ] = [ f ( n ) f ( n − 1 ) ] \left[ \begin{array}{cc} a& b \\ 1& 0 \\ \end{array} \right ] \left[\begin{array}{c} f(n-1) \\ f(n-2) \\ \end{array} \right]=\left[\begin{array}{c} f(n) \\ f(n-1)\end{array} \right] [a1b0][f(n1)f(n2)]=[f(n)f(n1)]

对于斐波那契数列,有

[ 1 1 1 0 ] [ F n − 1 F n − 2 ] = [ F n F n − 1 ] \\ \left[ \begin{array}{cc} 1& 1 \\ 1& 0 \\ \end{array} \right ] \left[\begin{array}{c} F_{n-1} \\ F_{n-2} \\ \end{array} \right]=\left[\begin{array}{c} F_{n} \\ F_{n-1}\end{array} \right] [1110][Fn1Fn2]=[FnFn1]

[ 1 1 1 0 ] n − 2 [ F 2 F 1 ] = [ F n F n − 1 ] \\ \left[ \begin{array}{cc} 1& 1 \\ 1& 0 \\ \end{array} \right ]^{n-2} \left[\begin{array}{c} F_{2} \\ F_{1} \\ \end{array} \right]=\left[\begin{array}{c} F_{n} \\ F_{n-1}\end{array} \right] [1110]n2[F2F1]=[FnFn1]

只要求出左边的系数矩阵就能求出 F n . F_{n}. Fn. 下面的代码演示如何用矩阵快速幂计算第 50 50 50 个斐波那契数( 125 , 8626 , 9025 125,8626,9025 125,8626,9025)。测试了一下,好像没有多快。

using ull = unsigned long long;
template <ull size>
struct Matrix
{
	ull a[size][size];

	Matrix()
	{
		memset(a, 0, sizeof(a));
		for (ull i = 0; i < size; ++i)
			a[i][i] = 1;
	}

	Matrix(const Matrix<size> &t) { memcpy(a, t.a, sizeof(a)); }

	Matrix<size> &operator=(const Matrix<size> &t)
	{
		memcpy(a, t.a, sizeof(a));
		return *this;
	}

	Matrix<size> operator*(const Matrix<size> &t)
	{
		Matrix<size> ret;
		for (ull i = 0; i < size; ++i)
		{
			for (ull j = 0; j < size; ++j)
			{
				ret.a[i][j] = 0;
				for (ull k = 0; k < size; ++k)
					ret.a[i][j] += a[i][k] * t.a[k][j];
			}
		}
		return ret;
	}

	Matrix<size> pow(ull n)
	{
		if (n < 2) return *this;
		Matrix<size> ret, b(*this);
		while (n)
		{
			if (n & 1) ret = ret * b;
			b = b * b;
			n >>= 1;
		}
		return ret;
	}
};

int main()
{

	Matrix<2> m;
	ull a[2][2] = {{1, 1}, {1, 0}};

	memcpy(m.a, a, sizeof(a));

	Matrix<2> t(m);
	t = t.pow(50 - 2);
	printf("%llu\n", t.a[0][0] + t.a[0][1]);
	return 0;
}

辗转相除法

欧几里得(Euclid) 先提出的,所以又叫欧几里得算法(Euclidean algorithm)。可以求最大公约数。

实现

递归或者循环

int gcd(int a, int b) 
{ return b ? gcd(b, a % b) : a; }
int gcd(int a, int b) 
{
	while(b)
	{
		int t = a % b;
		a = b;
		b = t;
	}
	return a;
}

更相减损术的实现与此类似,但效率极低。

效率

O ( log ⁡ ( min ⁡ { a , b } ) ) \Omicron\left(\log{\left(\min{\{a,b}\}\right)}\right) O(log(min{a,b}))

证明如下

以辗转相除法的循环实现为例,设用辗转相除法求 a , b a,b a,b 的最大公约数需要 N N N 次循环,其中 a > b . a > b. a>b. 约定 F i F_{i} Fi 表示第 i i i 个斐波那契数、 φ \varphi φ 表示黄金比例,则 F 1 = F 2 = 1. F_{1} = F_{2} = 1. F1=F2=1.

显然,当 N N N 的值确定时, a , b a,b a,b 的最小值应该分别为第 F N + 2 F_{N+2} FN+2 F N + 1 . F_{N+1}. FN+1. 想一想为什么。 即,若该算法需要 N N N 次循环,则有 b ≥ F N + 1 . b \ge F_{N+1}. bFN+1.

易得

F N + 1 ≥ φ N − 1 F_{N + 1}\ge \varphi^{N-1} FN+1φN1

所以 b ≥ φ N − 1 b\ge \varphi^{N-1} bφN1 ,即

N ≤ log ⁡ b log ⁡ φ + 1 N\le\frac{ \log{b}}{\log{\varphi}} + 1 Nlogφlogb+1

O ( N ) = O ( log ⁡ ( min ⁡ { a , b } ) ) .      ■ \Omicron(N) = \Omicron(\log{\left(\min{\{a,b}\}\right)}).\;\; \texttt{■} O(N)=O(log(min{a,b})).

证明辗转相除法的时间复杂度是斐波那契数列的第一个实际应用。

应用

最小公倍数

int lcm(int a, int b)
{	return a / gcd(a, b) * b; }

最大公约数的性质

已知两正整数 a > b , a>b, a>b, gcd ⁡ ( a , b ) \gcd\left(a,b\right) gcd(a,b) a , b a,b a,b 的最大公约数:

  • gcd ⁡ ( a , b ) = gcd ⁡ ( b , a ) \gcd\left(a, b\right) = \gcd\left(b, a\right) gcd(a,b)=gcd(b,a)交换律

  • a , b a,b a,b 任意的公约数都是 gcd ⁡ ( a , b ) \gcd(a, b) gcd(a,b) 的约数

  • gcd ⁡ ( a , b ) = gcd ⁡ ( a ± b , b ) \gcd\left(a, b\right) = \gcd\left(a\pm b, b\right) gcd(a,b)=gcd(a±b,b)更相减损法 的原理)

  • gcd ⁡ ( a , b ) = gcd ⁡ ( b , a   m o d   b ) \gcd\left(a, b\right) = \gcd\left(b, a\bmod b\right) gcd(a,b)=gcd(b,amodb)辗转相除法 的原理)

  • gcd ⁡ ( a , gcd ⁡ ( b , c ) ) = gcd ⁡ ( gcd ⁡ ( a , b ) , c ) \gcd\left(a,\gcd\left(b,c\right)\right)=\gcd\left(\gcd\left(a,b\right),c\right) gcd(a,gcd(b,c))=gcd(gcd(a,b),c)结合律

素数筛

一种算法,作用是除去连续整数中的合数、并留下其中的质数。

埃拉托瑟尼筛

你也想和我一样口算 1030 mod 11 吗?_第1张图片
(图片来源:维基共享资源)
The Sieve of Eratosthenes,最朴素的素数筛。实现简单、效率高。

实现

下面创建一个布尔数组 not_prime,记录区间 [ 1 , r ] \left [ 1, r\right ] [1,r] 中的数是否为合数。如果是合数,则对应值为 true。数组长度可以用素数计数函数的估计值来确定。prime_list 保存的就是区间 [ 1 , r ] \left [ 1, r\right ] [1,r] 中的所有素数。

bool not_prime[length];
vector<int> prime_list;

void sieve(int r)
{
	for(int i = 2; i <= r; ++i)
	{
		if(!not_prime[i]) prime_list.push_back(i);
		for(int j = i + i; j <= r; j += i)
			not_prime[j] = true;
	}
}

效率

O [ n log ⁡ ( log ⁡ n ) ] \Omicron\left[n \log{\left(\log{n}\right)}\right] O[nlog(logn)]

你问我怎么证明?太难了不会

积性函数

Multiplicative function

数论中的积性函数是指一个定义域为正整数集、陪域为复数集的函数,且有如下性质:

  • f ( 1 ) = 1 f(1) = 1 f(1)=1
  • a , b a,b a,b 互质时, f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b)

若一个积性函数有如下性质,则它是完全积性函数(completely multiplicative function)

  • 对任意两个正整数 a , b , a,b, a,b, f ( a b ) = f ( a ) f ( b ) f(ab)=f(a)f(b) f(ab)=f(a)f(b) 成立。

在数论以外的其他数学领域中研究的积性函数通常是指完全积性函数。如果没有特殊说明,下文中的所有“积性函数”均指不完全积性函数。

欧拉函数

Euler’s Totient Function

φ ( x ) = x    ∏ ( 1 − 1 p i ) \varphi\left ( x\right )=x\;\prod\left (1-\frac{1}{p_{i}}\right ) φ(x)=x(1pi1)

φ ( x ) \varphi\left ( x\right ) φ(x) [ 1 , x ] [1,x] [1,x] 中与 x x x 互质的数的个数。诸 p i p_{i} pi x x x 的质因数。因为1与1的最大公约数是1,所以1与1互质。 φ ( 1 ) = 1. \varphi\left(1\right)=1. φ(1)=1. 欧拉函数是积性函数

常用性质

  • 依其意义,对任意质数 p ,    p,\; p,    φ ( p ) = p − 1 \;\varphi\left(p\right)=p-1 φ(p)=p1

    • φ ( 2 ) = 1 \varphi\left(2\right)=1 φ(2)=1
  • 对任意奇数 n ,    n,\; n,    φ ( 2 n ) = φ ( 2 ) φ ( n ) = φ ( n ) , \;\varphi\left(2 n\right)=\varphi\left(2\right)\varphi\left(n\right)=\varphi\left(n\right), φ(2n)=φ(2)φ(n)=φ(n), 因为 2 与所有奇数互质;

  • 对任意质数 p p p 及任意正整数 k ,    k,\; k,    φ ( p k ) = p k − p k − 1 , \;\begin{aligned}\varphi\left(p^{k}\right)=p^{k}-p^{k-1}\end{aligned}, φ(pk)=pkpk1, 因为在 [ 1 , p k ] \left[1,p^{k}\right] [1,pk] 中,不与 p k p^{k} pk 互质的数只有 p p p 的倍数,共 p k − 1 p^{k-1} pk1

  • n > 2    n>2\; n>2 时, φ ( n ) \varphi\left(n\right) φ(n) 为偶数

    • n n n a a a 互质,即 gcd ⁡ ( n , a ) = 1 \gcd\left(n, a\right) = 1 gcd(n,a)=1,由 gcd ⁡ ( n , n − a ) = gcd ⁡ ( n , a ) = 1 \gcd\left(n, n-a\right) = \gcd\left(n, a\right) = 1 gcd(n,na)=gcd(n,a)=1 n n n n − a n-a na 互质,故 n n n 互质的数都是成对出现的,且每一对的和均为 n n n n > 2 n>2 n>2 时)
    • 故, [ 1 , n ] \left[1,n\right] [1,n] 中,所有与 n n n 互质的数之和为    1 2   n   φ ( n ) \;\begin{aligned}\frac{1}{2}\,n\,\varphi\left(n\right)\end{aligned} 21nφ(n) n > 2 n>2 n>2 时)

欧拉反演

n = ∑ d   ∣   n φ ( d ) n=\sum_{d\:\mid\: n}{\varphi\left(d\right)} n=dnφ(d)

证明

定义函数

f ( n ) = ∑ d   ∣   n φ ( d ) f\left(n\right)=\sum_{d\:\mid\: n}{\varphi\left(d\right)} f(n)=dnφ(d)

对任意一对互质的正整数 m , n m,n m,n

f ( m ) f ( n ) = ∑ i   ∣   m φ ( i ) ∑ j   ∣   n φ ( j ) = ∑ i   ∣   m ∑ j   ∣   n φ ( i ) φ ( j ) f\left(m\right)f\left(n\right)=\sum_{i\:\mid\: m}{\varphi\left(i\right)}\sum_{j\:\mid\: n}{\varphi\left(j\right)}=\sum_{i\:\mid\: m}{\sum_{j\:\mid\: n}{\varphi\left(i\right)\varphi\left(j\right)}} f(m)f(n)=imφ(i)jnφ(j)=imjnφ(i)φ(j)
= ∑ i   ∣   m ∑ j   ∣   n φ ( i   j ) = ∑ i   ∣   m n φ ( i ) = f ( m n ) =\sum_{i\:\mid\: m}{\sum_{j\:\mid\: n}{\varphi\left(i\,j\right)}}=\sum_{i\:\mid\: mn}{\varphi\left(i\right)}=f\left(mn\right) =imjnφ(ij)=imnφ(i)=f(mn)

因此, f ( n ) f\left(n\right) f(n) 是积性函数

对任意质数 p p p 及任意正整数 k k k

f ( p k ) = ∑ t = 0 k φ ( p t ) = 1 + ( p − 1 ) + ( p 2 − p ) + ⋯ + ( p k − p k − 1 ) = p k f\left(p^{k}\right)=\sum^{k}_{t=0}\varphi\left(p^{t}\right)=1+\left(p-1\right)+\left(p^{2}-p\right)+\cdots +\left(p^{k}-p^{k-1}\right)=p^{k} f(pk)=t=0kφ(pt)=1+(p1)+(p2p)++(pkpk1)=pk
大于 1 的正整数 n n n 可以分解为若干个质数的积,即

n = ∏ p i a i n=\prod{p_{i}^{a_{i}}} n=piai

其中,诸 p i p_i pi n n n 的质因数,诸 a i a_i ai 为对应质因数 p i p_i pi 的出现次数。

f ( n ) f\left(n\right) f(n)为积性函数,故

f ( n ) = f ( ∏ p i a i ) = ∏ f ( p i a i ) = ∏ p i a i = n .      ■ f\left(n\right)=f\left(\prod{p_{i}^{a_{i}}}\right)=\prod{f\left(p_{i}^{a_{i}}\right)}=\prod{p_{i}^{a_{i}}}=n.\;\; \texttt{■} f(n)=f(piai)=f(piai)=piai=n.

欧拉筛

The Sieve of Euler,一种素数筛。因为其时间复杂度为线性,所以又叫线性筛

上文中提到的埃氏筛有一个小问题——很多合数会被重复筛除。比如说 30 。由于 30 有质因数 2, 3, 5,埃氏筛会分别以 2 × 15 2\times15 2×15 3 × 10 3\times10 3×10 5 × 6 5\times6 5×6 这三种分解式来筛除 30。30 就被筛除了三次。

理论上, 如果我们能避免重复的筛除,就能提升效率。如何避免重复的筛除呢?

任意一个合数 n n n 都可以分解为 p × m p\times m p×m 的形式,其中 p p p n n n最小质因子。我们每次只用合数的最小质因子来筛除这个合数就能避免重复筛除

实现

bool not_prime[length];
vector<int> prime_list;

void sieve(int r)
{
	for (int i = 2; i <= r; ++i)
	{
		if (!not_prime[i]) prime_list.push_back(i);
		for (const auto& p : prime_list)
		{
			if (i * p > r) break;
			not_prime[i * p] = true;
			if (i % p == 0) break; // 注
		}
	}
}

:这一行保证了每次筛除的合数的最小质因数是 p p p想一想为什么。

效率

O ( n ) \Omicron(n) O(n)

然而有测试表明,当目标区间分别为 [1, 1e5]、[1, 1e6]、[1, 1e7] 时,埃氏筛都比线性筛快。

原理和应用

线性筛的实质就是把正整数的最小质因数分解出来,筛除合数的时候也是用到了它的实质。

只要稍加修改,上面的线性筛代码就可以算出诸数的质因数个数、诸数的质因数种数及诸数的最小质因数的出现次数

int num_of_p_factor[length];		// 质因数个数
int variety_of_p_factor[length];	// 质因数种数
int cnt_of_min_p_factor[length];	// 因数中的最小质因数计数器
vector<int> prime_list;

void sieve(int r)
{
	int num = 0;
	for (int i = 2; i <= r; ++i)
	{
		if (num_of_p_factor[i] == 0)
		{	// i 是质数
			prime_list.push_back(i);
			num_of_p_factor[i] = 1;
			cnt_of_min_p_factor[i] = 1;
			variety_of_p_factor[i] = 1;
		}
		for (const auto& j : prime_list)
		{
			if(i * j > r) break;
			num_of_p_factor[i * j] = num_of_p_factor[i] + 1;
			variety_of_p_factor[i * j] = variety_of_p_factor[i] + 1;
			if (i % j == 0)
			{
				--variety_of_p_factor[i * j];
				cnt_of_min_p_factor[i * j] = cnt_of_min_p_factor[i] + 1;
				break;
			}
			cnt_of_min_p_factor[i * j] = 1;
		}
	}
}

生成积性函数的函数值表

因为线性筛能把正整数的最小质因数分解出来,所以线性筛也经常与 积性函数的递推关系式 结合来 生成积性函数的函数值表。下面以欧拉函数为例说明其过程:

对于 φ ( n ) \varphi\left(n\right) φ(n)

  • n n n 为质数,则 φ ( n ) = n − 1 \varphi\left(n\right) = n-1 φ(n)=n1
  • n n n 可以分解为 p × m p\times m p×m,且 p p p n n n 的最小质因数:
    • p p p 不能整除 m m m,则 p p p m m m 互质,故 φ ( n ) = φ ( p ) φ ( m ) = ( p − 1 ) φ ( m ) \varphi\left(n\right) =\varphi\left(p\right)\varphi\left(m\right) =\left(p-1\right)\varphi\left(m\right) φ(n)=φ(p)φ(m)=(p1)φ(m)
    • p p p 能整除 m m m,依欧拉函数的意义可知 φ ( p m ) = p   φ ( m ) \varphi\left(pm\right) =p\:\varphi\left(m\right) φ(pm)=pφ(m),故 φ ( n ) = p   φ ( m ) \varphi\left(n\right)=p\:\varphi\left(m\right) φ(n)=pφ(m)

All problems in computer science can be solved by another level of indirection.

——大卫·惠勒(David John Wheeler)

抽象一下,通过线性筛生成积性函数的函数值表的格式如下:

对于 f ( n ) f\left(n\right) f(n)

  • n n n 为质数,那就直接计算 f ( n ) f\left(n\right) f(n)
  • n n n 可以分解为 p × m p\times m p×m,且 p p p n n n 的最小质因数:
    • p p p 不能整除 m m m,则 p p p m m m 互质,故 f ( n ) = f ( p ) f ( m ) f\left(n\right) =f\left(p\right)f\left(m\right) f(n)=f(p)f(m)
    • p p p 能整除 m m m,其实这种情况有点麻烦。我们希望 f ( n ) f\left(n\right) f(n) 有与 f ( p ) f\left(p\right) f(p) f ( m ) f\left(m\right) f(m) 相关的递推式,就像欧拉函数那样。但是每种积性函数的性质又不全相同,这就要依实际情况来确定了。

线性筛有着神奇的能力,用它来筛质数就是杀鸡用牛刀,而且在数据很少的时候线性筛还比埃氏筛慢,筛质数就用埃氏筛就行了。

欧拉定理

Euler’s Theorem

对任意正整数 a , b a,b a,b,若 a a a b b b 互质,则

a φ ( b ) ≡ 1 ( m o d b ) a^{\varphi\left(b\right)}\equiv1\pmod b aφ(b)1(modb)

其中 φ ( n ) \varphi\left(n\right) φ(n) 为上文提到的欧拉函数。

推论

  • b b b 为质数,且 a a a b b b 互质,则 a b − 1 ≡ 1 ( m o d b ) \begin{aligned}a^{b-1}\equiv1\pmod b\end{aligned} ab11(modb)费马小定理,Fermat’s Little Theorem

  • a a a b b b 互质,则 a q ≡ a q   m o d   φ ( b ) ( m o d b ) \begin{aligned}a^{q}\equiv a^{q\bmod\varphi\left(b\right)}\pmod b\end{aligned} aqaqmodφ(b)(modb)

贝祖定理

Bézout’s identity,或称裴祖定理

对于任意整数 a , b , x , y , a,b,x,y, a,b,x,y, g g g gcd ⁡ ( a , b ) , \gcd \left(a,b\right), gcd(a,b), a x + b y ax+by ax+by 必为 g g g 的倍数,特别地,一定存在整数 x , y , x,y, x,y, 使 a x + b y = g . ax+by=g. ax+by=g.

证明

对于两个正整数 a , b , a,b, a,b, 我们钦定 h h h 是集合 A = { a x + b y ∣ ( x ; y ) ∈ Z 2 } \mathbb{A}=\{ax+by\mid(x;y)\in\mathbb{Z}^{2}\} A={ax+by(x;y)Z2} 中最小的正数。

假设集合 A \mathbb{A} A 中存在正数 m , m, m, 使得 m m m 不是 h h h 的整数倍。

利用带余除法,假定

m ÷ h = q ⋯ ⋯ r m\div h=q\cdots\cdots r m÷h=qr

0 ≤ r < h 0\le r< h 0r<h r = m − q h r=m-qh r=mqh

又因为 m , h ∈ A , m,h\in\mathbb{A}, m,hA, 所以 r ∈ A , r\in\mathbb{A}, rA, 这使得 h h h 不是 A \mathbb{A} A 中的最小的正数,矛盾。因此, A \mathbb{A} A 中的所有数都是 h h h 的整数倍。

所以, a , b a,b a,b 均为 h h h 的整数倍, h h h a , b a,b a,b 的公因数。钦定 g = gcd ⁡ ( a , b ) , g=\gcd(a,b), g=gcd(a,b), h ≤ g ⋯ ⋯ ( 1 ) h\le g\cdots\cdots(1) hg(1)

a = s g , b = t g , a=sg,b=tg, a=sg,b=tg, a x + b y = ( s x + t y ) g , ax+by=(sx+ty)g, ax+by=(sx+ty)g, 所以 A \mathbb{A} A 中的所有数都是 g g g 的整数倍。又 h ∈ A , h\in\mathbb{A}, hA, g ≤ h ⋯ ⋯ ( 2 ) g\le h\cdots\cdots(2) gh(2)

( 1 ) ( 2 ) (1)(2) (1)(2) h = g .      ■ h = g.\;\;\texttt{■} h=g.

推论

a , b a,b a,b 互质的充要条件是存在整数 x , y , x,y, x,y, 使 a x + b y = 1. ax+by=1. ax+by=1.

扩展辗转相除法

Extended Euclidean Algorithm ,又称 扩展欧几里得算法。可以在求得 a , b a,b a,b 的最大公约数的同时,找出整数 x , y x,y x,y ,使它们满足 贝祖等式

a x + b y = gcd ⁡ ( a , b ) . ax+by=\gcd\left(a,b\right). ax+by=gcd(a,b).

a a a 是负数,可以把问题转化为

∣ a ∣ ( − x ) + b y = gcd ⁡ ( ∣ a ∣ , b ) . \left|a\right| (-x)+by=\gcd\left(\left|a\right|,b\right). a(x)+by=gcd(a,b).

推导

g = gcd ⁡ ( a , b ) , g=\gcd(a,b), g=gcd(a,b), 并假设辗转相除法中第 i i i 步得出的两个数分别为 a i , b i a_{i},b_{i} ai,bi

a 1 x 1 + b 1 y 1 = a 2 x 2 + b 2 y 2 = g a_{1}x_{1}+b_{1}y_{1}=a_{2}x_{2}+b_{2}y_{2}=g a1x1+b1y1=a2x2+b2y2=g

a 2 = b 1 a_{2}=b_{1} a2=b1

b 2 = a 1 − ⌊ a 1 b 1 ⌋ × b 1 b_{2}=a_{1}-\lfloor \frac{a_{1}}{b_{1}}\rfloor\times b_{1} b2=a1b1a1×b1

x 1 = y 2 ,    y 1 = x 2 − ⌊ a 1 b 1 ⌋ × y 2 x_{1}=y_{2},\;y_{1}=x_{2}-\lfloor \frac{a_{1}}{b_{1}}\rfloor\times y_{2} x1=y2,y1=x2b1a1×y2

不失一般性地,有

x i = y i + 1 ,    y i = x i + 1 − ⌊ a i b i ⌋ × y i + 1 x_{i}=y_{i+1},\;y_{i}=x_{i+1}-\lfloor \frac{a_{i}}{b_{i}}\rfloor\times y_{i+1} xi=yi+1,yi=xi+1biai×yi+1

利用上述递推公式反向递推就能求出 x 1 , y 1 . x_{1},y_{1}. x1,y1.

实现

int xgcd(int a, int b, int &x, int &y)
{	// 递归实现
	if(b == 0)
	{
		x = 1, y = 0;
		return a;
	}
	int g = xgcd(b, a % b, x, y);
	int t = x;
	x = y;
	y = t - (a / b) * y;
	return g;
}
int xgcd(int a, int b, int &x,int & y)
{	// 循环实现
	x = 1, y = 0;
	int q, t;
	while(b)
	{
		q = a / b;
		t = a;
		a = b;
		b = t - q * b;

		t = x;
		x = y;
		y = t - q * y;
	}
	return a;
}

解空间

满足贝祖等式的 ( x , y ) (x,y) (x,y) 不止一组,假设我们已经用扩展辗转相除法得出了一组解 ( x 0 , y 0 ) , (x_0,y_0), (x0,y0), 另一组解为 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)

a x 1 + b y 1 = a x 0 + b y 0 ax_1+by_1=ax_0+by_0 ax1+by1=ax0+by0

x 1 − x 0 y 1 − y 0 = − b a \frac{x_1-x_0}{y_1-y_0}=-\frac{b}{a} y1y0x1x0=ab

我们期望上式右侧是既约分数 (想一想为什么),约分之,得

x 1 − x 0 y 1 − y 0 = − b / g a / g \frac{x_1-x_0}{y_1-y_0}=-\frac{b/g}{a/g} y1y0x1x0=a/gb/g

故诸

( x 0 + b g n ,    y 0 − a g n ) \left(x_0+\frac{b}{g}n,\;y_0-\frac{a}{g}n\right) (x0+gbn,y0gan)

均满足贝祖等式, n n n 为整数。

x x x 的最小非负数解为

( x 0   m o d   b g + b g )   m o d   b g . \left(x_0\bmod\frac{b}{g} +\frac{b}{g}\right)\bmod \frac{b}{g}. (x0modgb+gb)modgb.

线性同余方程

形如 a x ≡ b ( m o d n ) ax\equiv b\pmod n axb(modn) 的关于 x x x 的方程叫线性同余方程

线性同余方程有解的充要条件是 b 为 gcd(a,n) 的整数倍

证明如下

我们钦定上述线性同余方程有解。

假设 b b b 不是 gcd ⁡ ( a , n ) \gcd(a,n) gcd(a,n) 的整数倍。

存在整数 y , y, y, 满足

a x = n y + b ax=ny+b ax=ny+b

a x − n y = b ax-ny=b axny=b

由贝祖定理, b b b gcd ⁡ ( a , n ) \gcd(a,n) gcd(a,n) 的整数倍,矛盾。故线性同余方程有解的充要条件是 b b b gcd ⁡ ( a , n ) \gcd(a,n) gcd(a,n) 的整数倍。      ■ \;\; \texttt{■}

求解

线性同余方程可以转化为贝祖等式求解,构造 a x − n y = b = k gcd ⁡ ( a , n ) ax-ny=b=k\gcd(a,n) axny=b=kgcd(a,n) 即可。

x x x 的周期应为 b / gcd ⁡ ( a , n ) . b/\gcd(a,n). b/gcd(a,n).

模逆元

显然,在 a , b , m a,b,m a,b,m 均为正整数时,下列关系成立:

  • ( a + b )   m o d   m = ( a   m o d   m + b   m o d   m + m )   m o d   m (a+b)\bmod m=(a\bmod m+b\bmod m + m)\bmod m (a+b)modm=(amodm+bmodm+m)modm

  • ( a − b )   m o d   m = ( a   m o d   m − b   m o d   m + m )   m o d   m (a-b)\bmod m=(a\bmod m-b\bmod m + m)\bmod m (ab)modm=(amodmbmodm+m)modm

  • ( a b )   m o d   m = ( ( a   m o d   m ) ( b   m o d   m ) )   m o d   m (ab)\bmod m=((a\bmod m)(b\bmod m))\bmod m (ab)modm=((amodm)(bmodm))modm

我们通常利用上述关系,不断地对多次计算的中间结果求余,避免最终结果溢出。

但是,下列关系却一般不成立:

  • ( a ÷ b )   m o d   m = ( ( a   m o d   m ) ÷ ( b   m o d   m ) )   m o d   m (a\div b)\bmod m=((a\bmod m)\div(b\bmod m))\bmod m (a÷b)modm=((amodm)÷(bmodm))modm

因此一旦计算过程中有除法,上面正确的三个式子也不能用了。要是能简单地将求余操作分别移到被除数和除数的位置上,那么很多程序会简单很多。

类比实数域上的除法和乘法的关系,如果存在整数 c , c, c, 满足 b c ≡ 1 ( m o d m ) , bc\equiv 1 \pmod m, bc1(modm), 则有

( a ÷ b )   m o d   m = ( ( a   m o d   m ) ( c   m o d   m ) )   m o d   m (a\div b)\bmod m=((a\bmod m)(c\bmod m))\bmod m (a÷b)modm=((amodm)(cmodm))modm

从直觉上来说,就是“在模 m m m 的意义下, b b b 等于 c c c 的倒数”。请读者尝试证明该方法的合理性。

我们把上面的 c c c 叫做 “ b b b m m m模逆元(或模倒数)”,显然, b b b 也是 c c c 在模 m m m 意义下的模逆元;如果模逆元存在,它通常不唯一。

整数 a a a 对模数 m m m 有模逆元的充要条件是 a , m a,m a,m 互质

もしモジュロが素数じゃない数だったときのことを考えるとふるえて夜も眠れません。

—— AtCoder 某选手

证明如下

我们钦定整数 a a a 对模数 m m m 有模逆元 b . b. b.

假设 a , m a,m a,m 有一相同质因数 p , p, p, 则存在整数 x , y , x,y, x,y, 使得

a = p x , m = p y a=px,m=py a=px,m=py

又由

a b ≡ 1 ( m o d m ) ab\equiv 1\pmod m ab1(modm)

可得,存在整数 k , k, k, 满足

a b = m k + 1 ab=mk+1 ab=mk+1

p x b = p y k + 1 pxb=pyk+1 pxb=pyk+1

p ( x b − y k ) = 1 p(xb-yk)=1 p(xbyk)=1

显然 p = 1 , p=1, p=1, 这与上述假设矛盾。因此,整数 a a a 对模数 m m m 有模逆元的充要条件是 a , m a,m a,m 互质。 ■ \texttt{■}

利用欧拉定理求模逆元

欧拉定理:

a , m a,m a,m 互质时,有

a φ ( m ) ≡ 1 ( m o d m ) a^{\varphi\left(m\right)}\equiv 1\pmod m aφ(m)1(modm)

所以, a φ ( m ) − 1 a^{\varphi\left(m\right)-1} aφ(m)1 a a a 在模 m m m 意义下的模逆元。其中,欧拉函数的值可以用线性筛得出。一个特别常见的情况是,当 m m m 为质数时, a m − 2 a^{m-2} am2 为模逆元之一。 请读者尝试证明之。

利用扩展辗转相除法求模逆元

贝祖定理:

a , m a,m a,m 互质、即 gcd ⁡ ( a , m ) = 1 \gcd\left(a,m\right) = 1 gcd(a,m)=1 时,存在整数 x , y , x,y, x,y, 满足

a x + m y = 1 ax+my=1 ax+my=1

下面证明 x x x a a a 在模 m m m 意义下的模逆元:

a x + m y ≡ a x ≡ 1 ( m o d m ) .      ■ ax+my\equiv ax\equiv 1\pmod m.\;\; \texttt{■} ax+myax1(modm).

可用扩展辗转相除法(扩展欧几里得算法)求出 x . x. x.

孙子定理

中国剩余定理,Chinese remainder theorem

将多个线性同余方程联立,就得到了线性同余方程组

考虑如下形式的线性同余方程组:

x ≡ b i ( m o d m i ) ,      i ∈ { 1 , 2 , 3 , ⋯   , k } , k ∈ Z + . x\equiv b_i \pmod {m_{i}},\;\;i\in\{1,2,3,\cdots,k\},k\in\mathbb{Z^{+}}. xbi(modmi),i{1,2,3,,k},kZ+.

孙子定理:
若诸 m i m_i mi 两两互质,则上述方程组有解,通解可由下述方式得出:

M = ∏ m i ,    M i = M / m i , M=\prod{m_i},\; M_i=M/m_i, M=mi,Mi=M/mi, t i t_i ti M i M_i Mi m i m_i mi 的模逆元,则通解为

x = k M + ∑ a i t i M i x=kM+\sum {a_{i}t_{i}M_{i}} x=kM+aitiMi

其中 k k k 为整数。在模 M M M 的意义下,方程组只有一个解:

x = ∑ a i t i M i . x=\sum {a_{i}t_{i}M_{i}}. x=aitiMi.

证明:

因为诸 m i m_i mi 互质,所以 gcd ⁡ ( m i , M i ) = 1 , \gcd(m_i,M_i)=1, gcd(mi,Mi)=1, 所以 M i M_i Mi 有模 m i m_i mi 的模逆元 t i , t_i, ti, a i t i M i ≡ a i ( m o d m i ) ; a_{i}t_{i}M_{i}\equiv a_i \pmod {m_{i}}; aitiMiai(modmi); 对任意 j , j, j, i ≠ j i\neq j i=j 时, a j t j M j ≡ a i ( m o d m i ) ; a_{j}t_{j}M_{j}\equiv a_i \pmod {m_{i}}; ajtjMjai(modmi);

故,对任意 i , i, i,

x = a i t i M i + ∑ j ≠ i a j t j M j ≡ a i ( m o d m i ) . x=a_{i}t_{i}M_{i}+\sum_{j\neq i}{a_{j}t_{j}M_{j}}\equiv a_i\pmod{m_{i}}. x=aitiMi+j=iajtjMjai(modmi).

     ■ \;\;\texttt{■}

你可能感兴趣的:(数论)