杜教筛

Posted hnylmstea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了杜教筛相关的知识,希望对你有一定的参考价值。

快速求一个积性函数 (f) 的前缀和,

记为 (S)

[S(n)=sum_{i=1}^{n} f(i)]

考虑一个积性函数 (g)

[ egin{aligned} & sum_{i=1}^{n}(f*g)(i) =& sum_{i=1}^{n}sum_{d|n}^{i}f(d)g(frac{i}{n}) =& sum_{d=1}^ng(d)sum_{i=1}^{frac{n}{d}}f(i) =& sum_{d=1}^{n}g(d)S(frac{n}{d}) =& sum_{d=2}^ng(d)S(frac{n}{d})+g(1) imes S(n) end{aligned} ]

所以我们得到了最重要的式子:

[ g(1)S(n)=sum_{i=1}^{n}(f*g)(i)-sum_{d=2}^ng(d)S(frac{n}{d}) ]

所以我们只要构造出一个 (g) ,我们能快速求出它的前缀和以及 (f * g) 的前缀和,那么对后面的整数分块, 复杂度 (O(n^{frac{3}{4}})) , 如果预处理到 (5e6), 复杂度近似为 (O(n^{frac{2}{3}}))

伪代码:

ll GetSum(int n) { // 算 f 前缀和的函数
  //记忆化
  ll ans = sum( (f * g)(n) ); // 算 f * g 的前缀和
  // 以下这个 for 循环是数论分块
  for(ll l = 2, r; l <= n; l = r + 1) { // 注意从 2 开始
    r = (n / (n / l)); 
    ans -= (g_sum(r) - g_sum(l - 1)) * GetSum(n / l);
    // g_sum 是 g 的前缀和
    // 递归 GetSum 求解
  } return Sum(n) = ans;//记忆化 
}

常用公式:

[mu * 1 = epsilon]
[varphi * 1=Id]

一个小小的拓展:

(sum_{i=1}^nvarphi(i) imes i)

首先来了解一个结论:
[(varphi imes Id) * Id=n^2]

(手推一下)

这题就是求 (f=varphi imes Id) 的前缀和,

(g=Id)

[g(1)S(n)=sum_{i=1}^n(f*g)(i)-sum_{d=2}^ng imes S(frac{n}{d})]

[(f*g)(n)=n^2]

((f*g)(n)) 的前缀和为 (frac{n(n+1)(2n+1)}{6}).

然后就可以筛了。

以上是关于杜教筛的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3944 Sum —— 杜教筛

杜教筛题表(已完成)

杜教筛学习笔记

hdu5608杜教筛

杜教筛

杜教筛