Appearance
整除分块
又叫数论分块。
对于求和式:
cpp
for (int i = 2, j; i <= n; i = j + 1) {
j = n / (n / i);
// 求 [i, j] 的贡献
}多维整除分块
形如:
此时,分块区间
容易发现每个
cpp
for (int i = 1; i <= m; i++)
maxn = max(maxn, a[i]);
for (int i = 2, j; i <= maxn;i i = j + 1) {
j = maxn;
for (int k = 1; k <= m; k++) {
j = min(j, a[k] / (a[k] / i));
}
// 求 [i, j] 的贡献
}二次整除分块
形如:
时间复杂度:
cpp
for (int i = 1, j; i <= m; i = j + 1) {
auto now = n / (i * i);
j = sqrtl(n / now);
// 求 [i, j] 的贡献
}杜教筛
杜教筛用于求解一些积性函数前缀和:
构造积性函数
特别地:
令
预处理
递归过程中状态需要记忆化,通常使用哈希表维护。
特别地,若求一次
cpp
int sum_euler(int n) {
if (n <= 2e6)
return euler[n];
if (mem1.count(n))
return mem1[n];
int res = (1 + n) * n / 2;
for (int i = 2, j; i <= n;) {
j = n / (n / i);
res -= (j - i + 1) * sum1(n / i);
i = j + 1;
}
return mem1[n] = res;
}
int sum_mu(int n) {
if (n <= 2e6)
return mu[n];
if (mem2.count(n))
return mem2[n];
int res = 1;
for (int i = 2, j; i <= n;) {
j = n / (n / i);
res -= (j - i + 1) * sum2(n / i);
i = j + 1;
}
return mem2[n] = res;
}