杜教筛

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

记为 \(S\)

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

考虑一个积性函数 \(g\)

\[ \begin{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)\times 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}^n\varphi(i) \times i\)

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

(手推一下)

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

\(g=Id\)

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

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

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

然后就可以筛了。

转载于:https://www.cnblogs.com/cnyali-Tea/p/10415764.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值