23集训 Day4 数论

发布时间 2023-09-14 20:54:05作者: Hszzzx

快速幂

定义

快速幂,是一个在 \(\Theta(\log n)\) 的时间内计算 \(a^n\) 的小技巧,而暴力的计算需要 \(\Theta(n)\) 的时间。

解释

\[\because a^{b+c}=a^{b} \times a^{c},a^{2b}=a^{b}\times a^{b}=(a^{b})^2 \]

定义快速幂函数为 \(q(x,n)\),则

\[q(x, n) = \begin{cases} 1& b=0\\ a& b=1\\ q(a,b/2)^2&b\bmod 2 = 0\\ q(a,b/2)^2\times a&b\bmod 2 = 1\\ \end{cases} \]

实现

#include <iostream>
using namespace std;
long long a, b, p;
long long q(long long x, long long n)
{
    if(n == 0) return 1;
    long long r = 0;
    if(n == 1) return a;
    r = q(x, n / 2) % p;
    r = r * r % p;
    if(n % 2) r = r * x % p;
    return r;
}
int main()
{
    cin >> a >> b >> p;
    cout << a << "^" << b << " mod " << p << "=" << q(a, b) % p;
    return 0;
}

唯一分解定理

\(\forall n\in \mathbf{N}_+\) 均可以被分解为有限个质数的乘积。

调和级数

百度百科

定义

\(\sum\limits_{i=1}^{n}\dfrac{1}{i}\) 被称为调和级数,它是发散的,即没有极限。

调和级数的部分和

\(\sum\limits_{i=1}^{n}\dfrac{1}{i}=\ln n + \gamma+\epsilon_k\)。其中 \(\gamma\) 是欧拉-马歇罗尼常数,而 \(\epsilon_k\approx\dfrac{1}{2k}\) ,并且随着 \(k\) 趋于正无穷而趋于 \(0\)。这个结果由欧拉给出。

gcd 与 lcm

\(\forall A,B\in\mathbf{N}_+\),根据唯一分解定理,有 \(A=\prod\limits_{i=1}^{n}p_i^{a_{i}},B=\prod\limits_{i=1}^{n}p_i^{b_{i}}\),其中 \(p_i\) 为质数。

则有 \(\gcd(A,B)=\prod\limits_{i=1}^{n}p_i^{\min(a_i,b_i)}\)\(\text{lcm}(A,B)=\prod\limits_{i=1}^{n}p_i^{\max(a_i,b_i)}\)

还有 \(\min(a,b) +\max(a,b) = a+b\)

所以

\[\begin{aligned} \gcd(A,B)\times\text{lcm}(A,B)&=\prod\limits_{i=1}^{n}p_i^{\min(a_i,b_i)}\times\prod\limits_{i=1}^{n}p_i^{\max(a_i,b_i)}\\ &=\prod\limits_{i=1}^{n}p_i^{\min(a_i,b_i)}\times p_i^{\max(a_i,b_i)}\\ &=\prod\limits_{i=1}^{n}p_i^{\min(a_i,b_i)+\max(a_i,b_i)}\\ &=\prod\limits_{i=1}^{n}p_i^{a_i+b_i}\\ &=\prod\limits_{i=1}^{n}p_i^{a_i}+\prod\limits_{i=1}^{n}p_i^{b_i}\\ &=A\times B \\ \end{aligned} \]

自然对数的底

引入

银行推出了活动,定期存款存一年的 \(\frac{1}{n}\) 时,利率为 \(\frac{1}{n}\),求本金为 \(100\text{元}\) 时反复存取直至一年时最多能拿多少钱。

例:存半年能拿 \(100\times (1 + 50\%)^2 = 225\text{(元)}\)

化简一下,题意就变为了:求

\[\lim \limits_{n\to\infty}\left(1+\frac{1}{n}\right) \]

我们定义:

\[\lim \limits_{n\to\infty}\left(1+\frac{1}{n}\right)=e \]

其中 \(e\) 是一个无理数,其值约等于 \(2.718281828459\cdots\)

\(e\) 为底的对数被称为自然对数,简记为 \(\ln x\)。即 \(\log_ex=\ln x\)

\(\ln\) 读作 natural log,也可读作 /lɔn/)

exgcd

辗转相除法

\[\gcd(a,b)= \begin{cases} a &b=0\\ gcd(b, a\bmod b) &\text{otherwise}\\ \end{cases} \]

定义

扩展欧几里得算法(Extended Euclidean algorithm, EXGCD),常用于求

\[ax+by=\gcd(a,b) \]

的一组可行解。

推导过程

因为:

\[\gcd(a,b)=\gcd(b,a\bmod b)\\ a\bmod b = a-b\lfloor \frac{a}{b}\rfloor \]

就有:

\[\begin{aligned} ax+by&=\gcd(a,b)\\ bx'+\left(a-b\lfloor \frac{a}{b}\rfloor\right)y'&=gcd(b,a\bmod b)\\ bx'+ay'-b\lfloor \frac{a}{b}\rfloor y'&=gcd(b,a\bmod b)\\ ay'+b(x'-\lfloor \frac{a}{b}\rfloor y')&=gcd(b,a\bmod b)\\ \end{aligned} \]

即为:

\[ax+by=ay'+b(x'-\lfloor \frac{a}{b}\rfloor y') \]

\(b=0\) 时,有 \(x=1,y=0\)

\(b\neq 0\) 时,递归求解。

Code

void exgcd(int a, int b, int &x, int &y) {
	if (b == 0) {
		x = 1, y = 0; //递归边界
		return;
	}
	else {
		exgcd(b, a % b, x, y);
		int tmp = x;
		x = y, y = tmp - a / b * y; // 继续递归
	}
}

模运算意义下的逆元

定义

对于任意的 \(\gcd(a,p)=1\),存在唯一的 \(x(0\leq x\leq p-1)\),使得 \(ax\bmod p = 1\)。称 \(x\)\(a\)\(\bmod\ p\) 意义下的乘法逆元。

求法

exgcd

\[ax\bmod p = 1 \Leftrightarrow ax+py=1 \]

证明:

\[\because ax\bmod p=ax-p\lfloor \frac{ax}{p}\rfloor \]

\(y=\lfloor \dfrac{ax}{p} \rfloor\),则:

\[ax-py = 1 \]

用 exgcd 求解即可。

欧拉定理

欧拉(Euler)定理:

\[a^{\varphi(p)}\equiv 1 (\bmod\ p) \]

其中 \(\varphi\) 为欧拉函数,\(\varphi (n)\) 表示不大于 \(n\) 的整数中与 \(n\) 互质的数的个数,定义 \(\varphi(1) =1\)

\[a^{\varphi(p)}\bmod p=1 \]

\[a\times a^{\varphi(p)-1}\bmod p=1 \]

\(a\)\(\bmod\ p\) 意义下的乘法逆元为 \(a^{\varphi(p)-1}\)

费马小定理

费马小定理:当 \(p\) 为质数时,有 \(a^{p-1}\bmod p = 1\)

\(a\)\(\bmod\ p\) 意义下的乘法逆元为 \(a^{p-2}\)

\(p\) 为质数时,\(\varphi(p)=p-1\),故费马小定理求逆元是欧拉定理求逆元的一种特殊情况。

欧拉筛

筛质数

在欧拉筛中,每一个合数都是被最小的质因子筛掉。

void init(int n) {
	for (int i = 2; i <= n; ++i) {
		if (!vis[i]) {
			pri[cnt++] = i;
		}
		for (int j = 0; j < cnt && 1ll * i * pri[j] <= n; ++j) {
			vis[i * pri[j]] = 1;
			if (i % pri[j] == 0) { // 换言之,i 之前被 pri[j] 筛过了
				// 由于 pri 里面质数是从小到大的,所以 i 乘上其他的质数的结果一定会被
				// pri[j]的倍数筛掉,就不需要在这里先筛一次,所以这里直接 break 就好了
				break;
			}
		}
	}
}

因为 prime[] 中的质数是递增的,当 \(i\mid prime_j\),那么 \(i\times prime_{j+1}\) 一定会被 \(prime_j\) 乘 某个数 筛掉,接下来的数同理,因此在满足 i % prime[j] == 0 时即可 break

筛积性函数

积性函数的定义:

若函数 \(f(n)\) 满足 \(f(1)=1\)\(\forall x,y\in\mathbf{N}_+,\gcd(x,y)=1\) 都有 \(f(x\times y)=f(x)\times f(y)\),则 \(f(n)\) 为积性函数。

\(x\) 分类讨论:

  • \(x\) 为质数,则 \(f(x)\) 直接计算。
  • \(i\bmod prime_j \neq 0\),则根据积性函数定义,有 \(f(i\times prime_j)=f(i)\times f(prime_j)\)
  • \(i\bmod prime_j = 0\),则 \(i\) 的最小质因子也为 \(prime_j\),记 \(prime_j\)\(i\) 的质因数中出现次数为 \(t\),显然 \(\dfrac{i}{prime_j^t}\)\(prime_j^{t+1}\) 互质。所以 \(f(i\times prime_j)=f(\dfrac{i}{prime_j^t})\times f(prime_j^{t+1})\)

筛欧拉函数

易证 \(\varphi\) 为积性函数。

对于任意的质数 \(p\),有 \(\varphi(p)=p-1\)\(\varphi(p^a)=p^{a-1}(p-1)\)

证明:
\(p\) 为质数时,在不大于 \(p\) 的正整数中,每 \(p\) 个数就有 \(p-1\) 个数与 \(p\) 互质。
所以 \(\varphi(p^a)=p^a\times\frac{p-1}{p} = p^{a-1}(p-1)\)\(\Box\)

\[\begin{aligned} \varphi(n)&=\prod\varphi(p_i^{a_i})\\ &=\prod p_i^{a_i}\times \frac{p_i-1}{p_i}\\ &=\left(\prod p_i^{a_i}\right)\times \left(\prod\frac{p_i-1}{p_i}\right)\\ &=n\prod\frac{p_i-1}{p_i} \end{aligned} \]

\(x\) 分类讨论:

  • \(x\) 为质数,则 \(\varphi(x)=x-1\)
  • \(i\bmod prime_j \neq 0\),则根据积性函数定义,有 \(\varphi(i\times prime_j)=\varphi(i)\times \varphi(prime_j) = \varphi(i)\times (prime_j-1)\)
  • \(i\bmod prime_j = 0\),则 \(i\) 包含了 \(prime_j\) 的所有质因子,

\[\begin{aligned} \varphi(n) & = n \times \prod{\frac{p_i - 1}{p_i}} \\ & = prime_j \times i \times \prod{\frac{p_i - 1}{p_i}} \\ & = prime_j \times \varphi(i) \end{aligned} \]

Code:

//vis[i] 存储 i 是否为合数
void init() {
	for (int i = 2; i <= n; ++i) {
		if (!vis[i]) { 
			prime[++cnt] = i;
		}
		for (int j = 1; j <= cnt && i * prime[j] <= n; ++j) {
			vis[i * prime[j]] = true;
			if (i % prime[j] == 0) {
				break;
			}
		}
	}
}

博弈论

寄,没听懂