八月总结复习
20240806
20240806
线性求逆元
假设我们求取\(n\)关于质数\(p\)的逆元,即求取\(n^{-1}\)
我们设\(a= \lfloor \frac{p}{n} \rfloor , b=p\bmod n\)。则有
$a*n+b\equiv 0 (mod\ p) $
移项可得:
即:
所以:
code:
inv[0]=inv[1]=1;
for(int i=2;i<=n;i++){
inv[i]=(-p/i+p)*inv[p%i]%p;
}
P2303Longge的问题
简化式子
\(=\sum^n_{j=1}(j \cdot \sum^n_{i=1}[gcd(i/j,n/j)==j] (j|i,j|n))\)
\(=\sum^n_{j=1}(j \cdot \sum^n_{i=1}[gcd(i/j,n/j)==1] (j|i,j|n))\)
\(=\sum^n_{j=1}(j \cdot \varphi(n/j)(j|n))\)
\(=\sum_{j|n}(j \cdot \varphi(n/j))\)
数论整除分块
求\(\sum_{i=1}^n\lfloor \frac{n}{i} \rfloor\)
code:
#include <iostream>
long long H(int n) {
long long res = 0; // 储存结果
int l = 1, r; // 块左端点与右端点
while (l <= n) {
r = n / (n / l); // 计算当前块的右端点
// 累加这一块的贡献到结果中。乘上 1LL 防止溢出
res += 1LL * (r - l + 1) * (n / l);
l = r + 1; // 左端点移到下一块
}
return res;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t, n;
std::cin >> t;
while (t--) {
std::cin >> n;
std::cout << H(n) << '\n';
}
return 0;
}
对于常数 \(n\),使得式子
\(\left\lfloor\dfrac ni\right\rfloor=\left\lfloor\dfrac nj\right\rfloor\)成立且满足 \(i\leq j\leq n\) 的 \(j\) 值最大为\(\left\lfloor\dfrac n{\lfloor\frac ni\rfloor}\right\rfloor\)。即值 \(\left\lfloor\dfrac ni\right\rfloor\) 所在块的右端点为\(\left\lfloor\dfrac n{\lfloor\frac ni\rfloor}\right\rfloor\)
证明:
令\(k=\left\lfloor\dfrac ni\right\rfloor\)可以知道\(k\leq\dfrac ni\)。
所以\(\lfloor \frac{n}{k} \rfloor \geq\lfloor \frac{n}{\frac{n}{i}} \rfloor=\lfloor i \rfloor=i\)
所以\(j=max\)满足条件的所有\(i=i_{max}=\lfloor \frac{n}{k} \rfloor=\lfloor \frac{n}{\lfloor \frac{n}{i} \rfloor} \rfloor\)
莫比乌斯反演
证明
P2257
题意:
开始简化
我们知道
将\(n\)用\(gcd(i,j)\)替换
替换之后
我们有
当然这个式子看起来不能化简了但是如果直接枚举的话我们一定会T成sb
我们设\(T=dk\)
枚举一下\(T\)
分块
例子:区间和
我们将序列按每 s 个元素一块进行分块,并记录每块的区间和 \(b_i\)。
\(\underbrace{a_1, a_2, \ldots, a_s}_{b_1}, \underbrace{a_{s+1}, \ldots, a_{2s}}_{b_2}, \dots, \underbrace{a_{(s-1) \times s+1}, \dots, a_n}_{b_{\frac{n}{s}}}\)
最后一个块可能是不完整的(因为 \(n\) 很可能不是 \(s\) 的倍数),但是这对于我们的讨论来说并没有太大影响。
首先看查询操作:
若 \(l\) 和 \(r\) 在同一个块内,直接暴力求和即可,因为块长为 \(s\),因此最坏复杂度为\(O(s)\)。
若 \(l\) 和 \(r\) 不在同一个块内,则答案由三部分组成:以\(l\)开头的不完整块,中间几个完整块,以\(r\)结尾的不完整块。对于不完整的块,仍然采用上面暴力计算的方法,对于完整块,则直接利用已经求出的 \(b_i\) 求和即可。这种情况下,最坏复杂度为
\(O(\dfrac{n}{s}+s)\)。
接下来是修改操作:
若 \(l\) 和 \(r\) 在同一个块内,直接暴力修改即可,因为块长为 \(s\),因此最坏复杂度为 O(s)$。
若 \(l\) 和 \(r\)不在同一个块内,则需要修改三部分:以 \(l\) 开头的不完整块,中间几个完整块,以 \(r\) 结尾的不完整块。对于不完整的块,仍然是暴力修改每个元素的值(别忘了更新区间和 \(b_i\)),对于完整块,则直接修改 \(b_i\) 即可。这种情况下,最坏复杂度和仍然为 \(O(\dfrac{n}{s}+s)\)。
利用均值不等式可知,当\(\dfrac{n}{s}=s\),即 \(s=\sqrt n\) 时,单次操作的时间复杂度最优,为$ O(\sqrt n)$。

浙公网安备 33010602011771号