杜教筛

杜教筛

杜教筛可以在 O ( n 2 3 ) O(n ^{\frac{2}{3}}) O(n32) 的复杂度内求解积性函数的前缀和

设数论函数 f ( x ) f(x) f(x),求

∑ i = 1 n f ( i ) \sum_{i=1}^{n}f(i) i=1nf(i)

S ( n ) = ∑ i = 1 n f ( i ) S(n) = \sum \limits_{i=1} ^{n} f(i) S(n)=i=1nf(i),找一个数论函数 g ( x ) g(x) g(x) f ( x ) f(x) f(x) 做卷积

∑ i = 1 n f ∗ g = ∑ i = 1 n g ∗ f \sum_{i=1} ^ {n} f * g = \sum_{i=1} ^{n}g *f i=1nfg=i=1ngf

展开卷积

∑ i = 1 n ∑ d ∣ i g ( d ) f ( i d ) \sum_{i=1}^{n} \sum_{d \mid i}g(d)f(\frac{i}{d}) i=1ndig(d)f(di)

交换求和次序

∑ d = 1 n g ( d ) ∑ i = 1 ⌊ n d ⌋ f ( i ) \sum_{d=1} ^{n}g(d) \sum_{i=1}^{\lfloor\frac{n}{d} \rfloor} f(i) d=1ng(d)i=1dnf(i)

后半部分其实就是 S ( ⌊ n d ⌋ ) S(\lfloor\dfrac{n}{d} \rfloor) S(dn),换一下变量名得

∑ i = 1 n g ( i ) S ( ⌊ n i ⌋ ) \sum_{i=1} ^{n}g(i)S(\lfloor\frac{n}{i} \rfloor) i=1ng(i)S(in)

那么就有递推公式

g ( 1 ) S ( n ) = ∑ i = 1 n f ∗ g − ∑ i = 2 n g ( i ) S ( ⌊ n i ⌋ ) g(1)S(n) = \sum_{i=1} ^{n}f*g-\sum_{i=2}^{n} g(i)S(\lfloor\frac{n}{i} \rfloor) g(1)S(n)=i=1nfgi=2ng(i)S(in)

假设 ∑ i = 1 n f ∗ g \sum\limits _{i=1} ^{n}f*g i=1nfg 可以快速求出,后半部分则可以用数论分块求解

莫比乌斯函数前缀和

由狄利克雷卷积

ε = μ ∗ I \varepsilon = \mu * I ε=μI

h = ε , f = μ , g = I h=\varepsilon,f=\mu,g=I h=ε,f=μ,g=I 套用杜教筛

S ( n ) = ∑ i = 1 n ε ( i ) − ∑ i = 2 n I ( i ) S ( ⌊ n i ⌋ ) S(n) = \sum_{i=1} ^{n}\varepsilon(i)-\sum_{i=2}^{n} I(i)S(\lfloor\frac{n}{i} \rfloor) S(n)=i=1nε(i)i=2nI(i)S(in)

化简可得

S ( n ) = 1 − ∑ i = 2 n S ( ⌊ n i ⌋ ) S(n) = 1 - \sum_{i=2}^{n} S(\lfloor\frac{n}{i} \rfloor) S(n)=1i=2nS(in)

欧拉函数前缀和

法一:

先对欧拉函数用莫比乌斯反演

∑ i = 1 n φ ( i ) \sum_{i=1} ^{n}\varphi(i) i=1nφ(i)

展开欧拉函数

∑ i = 1 n ∑ j = 1 n [ gcd ⁡ ( i , j ) = 1 ] \sum_{i=1} ^{n} \sum_{j = 1} ^{n} [\gcd(i,j)=1] i=1nj=1n[gcd(i,j)=1]

莫比乌斯反演

∑ i = 1 n ∑ j = 1 n ∑ d ∣ gcd ⁡ ( i , j ) μ ( d ) \sum_{i=1}^{n} \sum_{j = 1} ^{n} \sum_{d \mid \gcd(i,j)}\mu(d) i=1nj=1ndgcd(i,j)μ(d)

交换求和次序

∑ d = 1 n μ ( d ) ⌊ n d ⌋ 2 \sum_{d=1} ^{n}\mu(d) \lfloor \frac{n}{d} \rfloor ^2 d=1nμ(d)dn2

那么就可以用前面的莫比乌斯函数前缀和来求解了

注意要减去 i = 1 , j = 1 i=1,j=1 i=1,j=1 的情况,并且 / 2 /2 /2

法二:

由狄利克雷卷积

I d = φ ∗ I Id = \varphi * I Id=φI

h = I d , f = φ , g = I h = Id,f=\varphi,g=I h=Id,f=φ,g=I 套用杜教筛

S ( n ) = ∑ i = 1 n I d ( i ) − ∑ i = 2 n I ( i ) S ( ⌊ n i ⌋ ) S(n) = \sum_{i=1} ^{n}Id(i)-\sum_{i=2}^{n} I(i)S(\lfloor\frac{n}{i} \rfloor) S(n)=i=1nId(i)i=2nI(i)S(in)

S ( n ) = ∑ i = 1 n i − ∑ i = 2 n S ( ⌊ n i ⌋ ) S(n) = \sum_{i=1} ^{n}i-\sum_{i=2}^{n} S(\lfloor\frac{n}{i} \rfloor) S(n)=i=1nii=2nS(in)

等差数列求和

S ( n ) = n ( n + 1 ) 2 − ∑ i = 2 n S ( ⌊ n i ⌋ ) S(n) = \frac{n (n + 1)}{2} - \sum_{i=2}^{n} S(\lfloor\frac{n}{i} \rfloor) S(n)=2n(n+1)i=2nS(in)

代码(两个函数一起求):

题目:洛谷P4213

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6 + 5;
int T, n, mobius[N], primes[N], cnt, sum[N];
bool st[N];
unordered_map<int, int> mp;
void get_mobius(int n) {
    mobius[1] = 1;
    for (int i = 2; i <= n; i ++) {
        if (!st[i]) {
            primes[cnt ++] = i;
            mobius[i] = -1;
        }
        for (int j = 0; primes[j] * i <= n; j ++) {
            int t = primes[j] * i;
            st[t] = 1;
            if (i % primes[j] == 0) {
                mobius[t] = 0;
                break;
            }
            mobius[t] = -mobius[i];
        }
    }
    for (int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + mobius[i];
}
int sum_mobius(int n) {
    if (n < N) return sum[n];
    if (mp[n]) return mp[n];
    int res = 1;
    for (int l = 2, r; l <= n; l = r + 1) {
        r = n / (n / l);
        res -= sum_mobius(n / l) * (r - l + 1);
    }
    return mp[n] = res;
}
int sum_phi(int n) {
    int res = 0;
    for (int l = 1, r; l <= n; l = r + 1) {
        r = n / (n / l);
        res += (sum_mobius(r) - sum_mobius(l - 1)) * (n / l) * (n / l);
    }
    return (res - 1) / 2 + 1;
}
signed main() {
    get_mobius(N - 1);
    cin >> T;
    while (T --) {
        cin >> n;
        cout << sum_phi(n) << " " << sum_mobius(n) << endl;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值