杜教筛学习笔记

前言

这里假设你已经会了以下东西:

  • 狄利克雷卷积
  • 莫比乌斯反演
  • 数论分块

正文

一切的开始

先来看一个题目(Bzoj 4805):

给你一个整数$n$,求以下东西:

求$\sum_{i=1}^n \varphi_i$

可以线性筛吧…但是如果$n\leq 2e9$呢?

杜教筛是啥?

设$\mathbf S(n)=\sum_{i=1}^n\mathbf f(i)$,其中$\mathbf f$是积性函数。

我们不妨设一个$\mathbf g$,不管它具体是啥,做一个狄利克雷卷积:

然后再求一个和:

然后还有:

前面减数就是我们之前推的那个东西,后面被减数可以数论分块递归算:

比如要求$\sum_{i=1}^n\mu(i)$

找一个积性函数让他们的狄利克雷卷积很好算:

我们知道$\mu$的逆为$1$,也就是说$(1\astμ)=\epsilon$

那么单位元的前缀和是1,舒服啊,所以取$\mathbf g(n)$为$\mathbf 1(n)=1$,

所以原式可化为:

那么回归到例题

这时我们要找一个$\mathbf g$使得$\mathbf g$和$\mathbf g \ast \varphi$的前缀和都很好算

这时我们想到了$\varphi=\mu*\mathbf{id}$,

所以啊:$\varphi*\mathbf 1=\mathbf{id}$,则这里同样取$\mathbf g(n)$为$\mathbf 1(n)=1$

所以,杜教筛的重点就在于选取一个有利于计算的$\mathbf g$…

下面给出这题的代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using std::min; using std::max;
using std::swap; using std::sort;
typedef long long ll;

const int N = 2147483647, M = 2e6 + 10, K = 1.3e3 + 10;
ll phi[M], s1[M], s2[K]; bool vis[K], notprime[M];
int _n, prime[M], tot;

template<typename T>
void read(T &x) {
    int flag = 1; x = 0; char ch = getchar();
    while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
    while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}

ll S(int n) {
    if(n < M) return s1[n];
    int x = _n / n;
    if(vis[x]) return s2[x];
    vis[x] = true; ll &ans = s2[x];
    ans = 1ll * n * (n + 1) / 2;
    for(int i = 2, j; i <= n; i = j + 1)
        j = n / (n / i), ans -= (j - i + 1) * S(n / i);
    return ans;
}

void get_phi() {
    phi[1] = 1;
    for(int i = 2; i < M; ++i) {
        if(!notprime[i]) prime[++tot] = i, phi[i] = i - 1;
        for(int j = 1; j <= tot && i * prime[j] < M; ++j) {
            notprime[i * prime[j]] = true;
            if(!(i % prime[j])) { phi[i * prime[j]] = phi[i] * prime[j]; break; }
            else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
        }
    }
}

int main () {
    read(_n), get_phi();
    for(int i = 1; i < M; ++i) s1[i] = s1[i - 1] + phi[i];
    printf("%lld\n", S(_n));
    return 0; 
}

一些例题:

  • Bzoj3512 DZY Loves Math IV
  • LuoguP3768 简单的数学题