欧拉函数 整除分块 扩展欧几里得
欧拉函数 \(\varphi(x)\) 表示求出 \(1 \le y \le x, \gcd(x, y) = 1\) 的 \(y\) 的数量。
对于一个质数 \(p\), \(\varphi(p) = p - 1\)
\(\varphi(p^2) = p^2 - \frac{p^2}{p} = p^2 - p\)
\(\dots\)
\(\varphi(p^i) = p^i - p^{i - 1} = (p - 1) \cdot p^{i - 1}\)
它是一个积性函数 \(\varphi(a \cdot b) = \varphi(a) \cdot \varphi(b), \gcd(a, b) = 1\)。
求\(\varphi(x)\), 令 \(x\) 的质因数分解形式为 \(p_1^{e_1} \cdot p_2^{e_2} \dots p_n^{e_n}\), 通过积性函数的性质 \(\varphi(x) = \varphi(p_1^{e_1}) \cdot \varphi(p_2^{e_2}) \dots \varphi(p_n^{e_n})\)。
\(O(\sqrt{n})\) 的时间内求出 \(\varphi(n)\)
伪代码
int phi(int x){
long long ans = 1;
for(int i = 2; i * i <= x; ++i){
if(x % i == 0){
ans *= (i - 1);
x /= i;
for(; x % i == 0; x /= i, ans *= i){
}
}
}
if(x > 1){
ans *= (x - 1);
}
return ans;
}
欧拉筛可以在 \(O(n)\) 的时间内求出 \(1\) ~ \(n\) 的 \(\varphi(i)\)。
\(n \leftarrow \frac{n}{p_1},\frac{n}{p_2} \dots\) 转移过来,不过稿欧拉筛的 break
降低成 \(O(n)\)。
令 \(p_1 < p_2 \dots\)
\(p_1 | \frac{n}{p_2}, p_1 | \frac{n}{p_3} \dots\)
所以枚举 \(\frac{n}{p_2}, \frac{n}{p_3} \dots\) 都会被弹掉。
void INT(){
p[1] = 1;
for(int i = 2; i <= n; ++i){
if(!p[i]){
p[i] = i - 1;
e.push_back(i);
}
for(auto x : e){
if(i * x > n){
break;
}
if(i % x == 0){
p[i * x] = 1ll * p[i] * x;
break;
}
p[i * x] = 1ll * p[i] * (x - 1);
}
}
}
整除分块
求出 \(\sum \limits_{i = 1}^{n} \lfloor \frac{n}{i} \rfloor\)
只有 \(O(\sqrt{n})\) 的值
- 若 \(i \le \sqrt{n}\), \(\lfloor \frac{n}{i} \rfloor\) 最多有 \(\sqrt{n}\) 种取值。
- 若 \(i > \sqrt{n}\), \(\lfloor \frac{n}{i} \rfloor \le \sqrt{n}\), 最多有 \(\sqrt{n}\) 种取值。
扩展欧几里得
\(\gcd(a, b) = \gcd(b, a \bmod b) = \dots \gcd(x, 0) = x\)
当 \(b = 0\) 是, \(x = 1, y = k\) 时是一组合法解, \(k\) 为任意整数。
求出一组解满足 \(ax + by = \gcd(a, b)\)
\(ax + by = \gcd(a, b)\)
\(b \cdot x' + (a - \lfloor \frac{a}{b} \rfloor \cdot b) \cdot y' = \gcd(b, a \bmod b)\)
\(b \cdot x' + a \cdot y' - \lfloor \frac{a}{b} \rfloor \cdot y' = \gcd(b, a \bmod b)\)
\(a \cdot y + b \cdot (x' - \lfloor \frac{a}{b} \rfloor \cdot y') = \gcd(b, a \bmod b)\)
\(ax + by = \gcd(a, b) = a \cdot y + b \cdot (x' - \lfloor \frac{a}{b} \rfloor \cdot y')\)
所以当 \(x = y', y = (x' - \lfloor \frac{a}{b} \rfloor \cdot y')\) 时是一组合法解。
伪代码
struct Node{
long long x, y;
};
Node exgcd(int a, int b){
if(!b){
return {1, 0};
}
Node now = exgcd(b, a % b);
return {now.y, now.x - a / b * now.y};
}