P4213 【模板】杜教筛 - 教程

题目描述

给定一个正整数 n n n,求

a n s 1 = ∑ i = 1 n φ ( i ) ans_1=\sum_{i=1}^n\varphi(i) ans1=i=1nφ(i)

a n s 2 = ∑ i = 1 n μ ( i ) ans_2=\sum_{i=1}^n \mu(i) ans2=i=1nμ(i)

输入格式

本题单测试点内有多组数据

输入的第一行为一个整数,表示数据组数 T T T

接下来 T T T 行,每行一个整数 n n n,表示一组询问。

输出格式

对于每组询问,输出一行两个整数,分别代表 a n s 1 ans_1 ans1 a n s 2 ans_2 ans2

输入输出样例 #1

输入 #1

6
1
2
8
13
30
2333

输出 #1

1 1
2 0
22 -2
58 -3
278 -3
1655470 2

说明/提示

数据规模与约定

对于全部的测试点,保证 1 ≤ T ≤ 10 1 \leq T \leq 10 1T10 1 ≤ n < 2 31 1 \leq n \lt 2^{31} 1n<231

好!把“杜教筛”(求积性函数的前缀和)的来龙去脉一步讲清楚。核心只有三件事:狄利克雷卷积恒等式把和式按 (\big\lfloor \frac n i\big\rfloor) 分块递归+记忆化


一、目标与思路

我们希望快速计算积性函数的前缀和
S f ( n ) = ∑ i = 1 n f ( i ) . S_f(n)=\sum_{i=1}^n f(i). Sf(n)=i=1nf(i).
杜教筛利用两点:
1)狄利克雷卷积恒等式;
2)按 ( ⌊ n i ⌋ \left\lfloor \frac{n}{i}\right\rfloor in) 分块(整除分块)+ 记忆化递归。


二、狄利克雷卷积与前缀和的关系

卷积定义:
( f ∗ g ) ( n ) = ∑ d ∣ n f ( d ) , g ( n / d ) . (f*g)(n)=\sum_{d\mid n} f(d),g(n/d). (fg)(n)=dnf(d),g(n/d).

若已知 (f*g=h),对 (k=1,\dots,n) 求和并换序:
∑ k = 1 n h ( k ) = ∑ k = 1 n ∑ d ∣ k f ( d ) g ( k / d ) = ∑ i = 1 n f ( i ) ∑ m = 1 ⌊ n / i ⌋ g ( m ) = ∑ i = 1 n f ( i ) , S g ! ( ⌊ n i ⌋ ) . \sum_{k=1}^n h(k) =\sum_{k=1}^n\sum_{d\mid k} f(d)g(k/d) =\sum_{i=1}^n f(i)\sum_{m=1}^{\lfloor n/i\rfloor} g(m) =\sum_{i=1}^n f(i),S_g!\Big(\Big\lfloor \frac{n}{i}\Big\rfloor\Big). k=1nh(k)=k=1ndkf(d)g(k/d)=i=1nf(i)m=1n/ig(m)=i=1nf(i),Sg!(in).


H ( n ) = ∑ k = 1 n h ( k ) , H(n)=\sum_{k=1}^n h(k), H(n)=k=1nh(k),

H ( n ) = ∑ i = 1 n f ( i ) , S g ! ( ⌊ n i ⌋ ) . H(n)=\sum_{i=1}^n f(i),S_g!\Big(\Big\lfloor \frac{n}{i}\Big\rfloor\Big). H(n)=i=1nf(i),Sg!(in).

当 ( g ( 1 ) ≠ 0 g(1)\neq 0 g(1)=0) 时,把 (i=1) 项单独拿出可写成
H ( n ) = f ( 1 ) , S g ( n ) + ∑ i = 2 n f ( i ) , S g ! ( ⌊ n i ⌋ ) . H(n)=f(1),S_g(n)+\sum_{i=2}^n f(i),S_g!\Big(\Big\lfloor \frac{n}{i}\Big\rfloor\Big). H(n)=f(1),Sg(n)+i=2nf(i),Sg!(in).
选择合适的 ( g g g)(使 ( S g S_g Sg) 易算),再把右侧转化为只含 ( S f ( ⌊ n / i ⌋ ) S_f(\lfloor n/i\rfloor) Sf(⌊n/i⌋)) 的递推。


三、两个经典目标函数

1. 欧拉函数 ( φ \varphi φ)

恒等式
φ ∗ 1 = i d , i d ( n ) = n , 1 ( n ) ≡ 1. \varphi * \mathbf{1} = \mathrm{id},\qquad \mathrm{id}(n)=n,\quad \mathbf{1}(n)\equiv 1. φ1=id,id(n)=n,1(n)1.
求和得
∑ k = 1 n k = ∑ i = 1 n φ ( i ) , ⌊ n i ⌋ . \sum_{k=1}^n k=\sum_{i=1}^n \varphi(i),\Big\lfloor \frac{n}{i}\Big\rfloor. k=1nk=i=1nφ(i),in.
左边
H ( n ) = n ( n + 1 ) 2 , S 1 ( x ) = x . H(n)=\frac{n(n+1)}{2},\qquad S_{\mathbf{1}}(x)=x. H(n)=2n(n+1),S1(x)=x.

用整除分块,把 ( ⌊ n / i ⌋ \lfloor n/i\rfloor n/i) 相同的 ( i ∈ [ l , r ] i\in[l,r] i[l,r]) 归为一块,块长为 ( ( r − l + 1 ) (r-l+1) (rl+1)),块内和为 ( S φ ( r ) − S φ ( l − 1 ) S_\varphi(r)-S_\varphi(l-1) Sφ(r)Sφ(l1))。整理可得常用递推式
S φ ( n ) = n ( n + 1 ) 2 − ∑ l = 2 n S φ ! ( ⌊ n l ⌋ ) , ( r − l + 1 ) , \boxed{S_\varphi(n)=\frac{n(n+1)}{2}-\sum_{l=2}^{n} S_\varphi!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),} Sφ(n)=2n(n+1)l=2nSφ!(ln),(rl+1),
其中
r = ⌊ n ⌊ n / l ⌋ ⌋ . r=\Big\lfloor \frac{n}{\lfloor n/l\rfloor}\Big\rfloor. r=n/ln.

初值:( S φ ( 1 ) = 1 S_\varphi(1)=1 Sφ(1)=1)。


2. 莫比乌斯函数 (\mu)

恒等式
μ ∗ 1 = ε , ε ( 1 ) = 1 ,   ε ( n > 1 ) = 0. \mu * \mathbf{1} = \varepsilon,\qquad \varepsilon(1)=1,\ \varepsilon(n>1)=0. μ1=ε,ε(1)=1,ε(n>1)=0.
求和得
1 = ∑ i = 1 n μ ( i ) , ⌊ n i ⌋ . 1=\sum_{i=1}^n \mu(i),\Big\lfloor \frac{n}{i}\Big\rfloor. 1=i=1nμ(i),in.
同样整除分块,得到
, S μ ( n ) = 1 − ∑ l = 2 n S μ ! ( ⌊ n l ⌋ ) , ( r − l + 1 ) , \boxed{,S_\mu(n)=1-\sum_{l=2}^{n} S_\mu!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),} ,Sμ(n)=1l=2nSμ!(ln),(rl+1),
其中 ( r = ⌊ n ⌊ n / l ⌋ ⌋ r=\left\lfloor \dfrac{n}{\lfloor n/l\rfloor}\right\rfloor r=n/ln)。

初值:( S μ ( 1 ) = 1 S_\mu(1)=1 Sμ(1)=1)。


实现注意事项(易错点)

  • ( S μ ( n ) ) S_\mu(n)) Sμ(n)) 的初值是 (1),不是 ( n ( n + 1 ) 2 \dfrac{n(n+1)}{2} 2n(n+1))。
  • 计算 ( n ( n + 1 ) 2 \dfrac{n(n+1)}{2} 2n(n+1)) 要用更大中间类型避免溢出.

七、两条公式一键记忆

  • 欧拉函数前缀和:
    S φ ( n ) = n ( n + 1 ) 2 − ∑ l = 2 n S φ ! ( ⌊ n l ⌋ ) , ( r − l + 1 ) , r = ⌊ n ⌊ n / l ⌋ ⌋ . S_\varphi(n)=\frac{n(n+1)}{2}-\sum_{l=2}^{n} S_\varphi!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),\qquad r=\Big\lfloor \frac{n}{\lfloor n/l\rfloor}\Big\rfloor. Sφ(n)=2n(n+1)l=2nSφ!(ln),(rl+1),r=n/ln.

  • 莫比乌斯前缀和:
    S μ ( n ) = 1 − ∑ l = 2 n S μ ! ( ⌊ n l ⌋ ) , ( r − l + 1 ) , r = ⌊ n ⌊ n / l ⌋ ⌋ . S_\mu(n)=1-\sum_{l=2}^{n} S_\mu!\Big(\Big\lfloor\frac{n}{l}\Big\rfloor\Big),(r-l+1),\qquad r=\Big\lfloor \frac{n}{\lfloor n/l\rfloor}\Big\rfloor. Sμ(n)=1l=2nSμ!(ln),(rl+1),r=n/ln.


时间复杂度: O ( n 2 / 3 ) O(n^{2/3}) O(n2/3)

模板

#include 
using namespace std;
typedef long long ll;
const int N=2e6+10;
ll n;
ll mu[N];
ll phi[N],pm[N];
unordered_mapmp_phi,mp_mu;
bool vis[N];
int cnt=0;
void init()
{
    mu[1]=phi[1]=1;
    for(ll i=2;i<=N-10;i++)
    {
        if(!vis[i])
        {
            pm[++cnt]=i;
            phi[i]=i-1;
            mu[i]=-1;
        }
        for(ll j=1;pm[j]*i<=N-10;j++)
        {
            ll p = pm[j];
            ll m = i*p;
            vis[m]=true;
            if(i%p==0)
            {
                phi[i*p]=phi[i]*p;
                break;
            }
            mu[m]=-mu[i];
            phi[i*p] = phi[i]*(p-1);
        }
    }
    for(int i=1;i<=N-10;i++)
    {
        mu[i]+=mu[i-1];
        phi[i]+=phi[i-1];
    }
}
ll sphi(ll n)
{
    if(n<=N-10)return phi[n];
    if(mp_phi[n])return mp_phi[n];
    ll ans = n*(n+1)/2;
    ll r;
    for(ll l=2;l<=n;l=r+1)
    {
        r = n/(n/l);
        ans -= sphi(n/l)*(r-l+1);
    }
    return mp_phi[n]=ans;
}
ll smu(ll n)
{
    if(n<=N-10)return mu[n];
    if(mp_mu[n])return mp_mu[n];
    ll ans = 1;
    ll r;
    for(ll l=2;l<=n;l=r+1)
    {
        r = n/(n/l);
        ans -= smu(n/l)*(r-l+1);
    }
    return mp_mu[n]=ans;
}
void solve()
{
    cin>>n;
    ll ans1 = sphi(n);
    ll ans2 = smu(n);
    cout<>t;
    init();
    while(t--)
    {
        solve();
    }
    return 0;
}
posted @ 2025-12-06 18:46  clnchanpin  阅读(17)  评论(0)    收藏  举报