前言

好久没更了,刚考完省选有点颓。

前置知识

概述

杜教筛用于在 的时间内求解某些函数的前缀和。

公式

杜教筛的核心公式如下:
为目标函数(即我们要求前缀和的函数)
为我们构造的一个函数。

其中 的狄利克雷卷积。

如果能找到一个合适的积性函数 ,能快速求出 ,那么就能使用数论分块递归求解了。

不一定要是积性函数。

证明


复杂度

假设算 的复杂度为 ,算 的复杂度为

通常情况下 都为


后面的那个可以忽略,于是


众所周知的杜教筛是 的,原因是可以先筛出前 个答案。复杂度变为 ,取 即可。

常见函数

再看例子前,可以先看看有哪些常作为 的函数。

下面 的狄利克雷卷积。

例子

函数前缀和

由于 ,所以取 ,那么

auto apiadu_sieve_phi = [&](auto& $, tp n) -> tp {
  if (n <= m || ps_phi.count(n)) return ps_phi[n];
  tp ret = n * (n + 1) / 2;
  for (tp l = 2, r; l <= n; l = r + 1) {
    r = n / (n / l);
    ret -= (r - l + 1) * $($, n / l);
  }
  return ps_phi[n] = ret;
};

函数前缀和

由于 ,所以取 ,那么

auto apiadu_sieve_mu = [&](auto& $, tp n) -> tp {
  if (n <= m || ps_mu.count(n)) return ps_mu[n];
  tp ret = 1;
  for (tp l = 2, r; l <= n; l = r + 1) {
    r = n / (n / l);
    ret -= (r - l + 1) * $($, n / l);
  }
  return ps_mu[n] = ret;
};

函数前缀和

这是一个经典例子。尽管 不再是积性函数,但我们任然可以杜教筛。

于是我们还是可以在常数时间内计算

卡常小技巧

参考

https://www.luogu.com.cn/article/tojxbb76
https://oi-wiki.org/math/number-theory/du/
https://www.luogu.com/article/hjw4837h