码迷,mamicode.com
首页 > 其他好文 > 详细

杜教筛

时间:2017-10-03 23:20:27      阅读:334      评论:0      收藏:0      [点我收藏+]

标签:func   mem   zoj   构造   快速   前缀   bzoj   模型   时间   

  快速求 $S(n) = \sum_{i = 1} ^ n f(i)$ .

 

  设 $g$ 为另外一个函数.

  $\begin{aligned} \sum_{i = 1} ^ n (f * g)(i) & = \sum_{i = 1} ^ n \sum_{d | i} f(d) g(\frac{i}{d}) \\ & = \sum_{k = 1} ^ n g(k) \sum_{d} [kd \le n] f(d) & 枚举 \frac{i}{d} \\ & = \sum_{k = 1} ^ n g(k) \sum_{d = 1} ^ {\lfloor \frac{n}{k} \rfloor} f(d) \\ & = \sum_{k = 1} ^ n g(k) S(\lfloor \frac{n}{k} \rfloor) \end{aligned}$ .

  $\begin{aligned} g(1) S(n) = \sum_{i = 1} ^ n (f * g)(i) - \sum_{k = 2} ^ n g(k) S(\lfloor \frac{n}{k} \rfloor) \end{aligned}$ .        --- 公式1

  假如能够找到合适的 $g$ , 支持快速计算 $g$ 的前缀和, 以及 $f * g$ 的前缀和, 就能根据公式1把 $S(n)$ 转化, 计算出 $S(n)$ .

 

  计算莫比乌斯函数的前缀和.

  设 $M(n) = \sum_{i = 1} ^ n \mu(i)$ .

  我们有 $[n = 1] = \sum_{k | n} \mu(k)$ , 即 $e = \mu * I$ .

  代入公式1得 $M(n) = 1 - \sum_{k = 2} ^ n k S(\lfloor \frac{n}{k} \rfloor)$ .

 

  时间复杂度为 $O(n ^ {\frac{3}{4}})$ .

  如果能快速预处理前 $O(n ^ {\frac{2}{3}})$ 项 (一般预处理 1000000 项) , 那么复杂度为 $O(n ^ {\frac{2}{3}})$ .

 

  计算欧拉函数的前缀和.

  设 $\Phi(n) = \sum_{i = 1} ^ n \phi(i)$ .

  $\phi * I = id$ .

  代入公式1得 $\Phi(n) = \frac{n(n+1)}{2} - \sum_{k = 2} ^ n k S(\lfloor \frac{n}{k} \rfloor)$ .

 

  [BZOJ 3944] Sum

  求 $M(n), \Phi(n), n \le 10 ^ 9$ .

 1 const int N = 1000000;
 2 
 3 bool v[N+5];
 4 int pri[N+5], tot;
 5 LL sum[2][N+5];
 6 map<int, LL> mem[2];
 7 
 8 inline LL pre(int n) { return n * (n+1LL) >> 1; }
 9 LL calc(int n, int sig) {
10     if (n <= N) return sum[sig][n];
11     if (mem[sig].count(n)) return mem[sig][n];
12     LL ans = (!sig ? 1 : pre(n));
13     for (int l = 2, r; 2 <= l && l <= n; l = r+1) {
14         int w = n / l;
15         r = n / w;
16         ans -= (r-l+1LL) * calc(w, sig);
17     }
18     return mem[sig][n] = ans;
19 }
20 
21 int main(void) {    
22     v[1] = true, sum[0][1] = sum[1][1] = 1;
23     F(i, 2, N) {
24         if (!v[i]) {
25             pri[++tot] = i;
26             sum[0][i] = -1, sum[1][i] = i-1;
27         }
28         for (int j = 1; j <= tot && i * pri[j] <= N; j++) {
29             v[i * pri[j]] = true;
30             if (i % pri[j] != 0) {
31                 sum[0][i * pri[j]] = -sum[0][i];
32                 sum[1][i * pri[j]] = sum[1][i] * (pri[j] - 1);
33             }
34             else {
35                 sum[1][i * pri[j]] = sum[1][i] * pri[j];
36                 break;
37             }
38         }
39     }
40     F(i, 1, N) {
41         sum[0][i] += sum[0][i-1];
42         sum[1][i] += sum[1][i-1];
43     }
44     
45     for (int nT = rd(), cc = 1; cc <= nT; cc++) {
46         int n = rd();
47         printf("%lld ", calc(n, 1));
48         printf("%lld\n", calc(n, 0));
49     }
50 }

 

  [HDU 5608] function

  题意

  $g(n) = n ^ 2 - 3n + 2 = \sum_{d | n} f(d)$ .

  求 $F(n) = \sum_{i = 1} ^ n f_i$ .

  分析

  $g = f * I$ .

  $g(1)F(n) = \sum_{i = 1} ^ n g(i) - \sum_{i = 2} ^ n I(i) F(\lfloor \frac{n}{i} \rfloor)$ .

  $F(n) = \sum_{i} (i ^ 2 - 3i + 2) - \sum_{i = 2} ^ n F(\lfloor \frac{n}{i} \rfloor)$ .

  预处理时手动反演.

  小结

  一个化简的模型: $g = f * I$  .

  那么 $F(n) = \sum_{i = 1} ^ n g(i) - \sum_{i = 2} ^ n F(\lfloor \frac{n}{i} \rfloor)$ .

 

  [51NOD 1238] 最小公倍数之和

  题意

  求 $\sum_{i = 1} ^ n \sum_{j = 1} ^ n [i, j]$ .

  分析

  我想起了一个简化版的问题: $\sum_{i = 1} ^ n [i, n]$ .

  $\begin{aligned} \sum_{i = 1} ^ n [i, n] & = n \sum_{i} \frac{i}{(i, n)} & \text{根据 LCM 与 GCD 的关系进行展开} \\ & = n \sum_k \frac{1}{k} \sum_{i} i [k = (i, n)] & \text{枚举 GCD} \\ & = n \sum_k \frac{1}{k} \sum_{i} i [k | i, k | n, \frac{i}{k} \perp \frac{n}{k}] \\ & = n \sum_k \frac{1}{k} \sum_{d} (dk) [d \perp \frac{n}{k}] & \text{枚举} \frac{i}{k} \\ & = n \sum_k \sum_d d [d \perp \frac{n}{k}] \\ & = n \sum_{k | n} \frac{\frac{n}{k} \phi(\frac{n}{k}) + [\frac{n}{k} = 1]}{2} & \text{利用欧拉函数的性质} \\ & = n \sum_{k | n} \frac{k \phi(k) + [k = 1]}{2} & \text{枚举} \frac{n}{k} \end{aligned}$

  尝试将该问题与这道题进行联系.

  $\begin{aligned} \sum_{i = 1} ^ n \sum_{j = 1} ^ n [i, j] & = \sum_{i = 1} ^ n \sum_{j \le i} [i, j] + \sum_{j = 1} ^ n \sum_{i \le j} [i, j] - \sum_{i = 1} ^ n [i, i] & 相互联系 \\ & = 2 \sum_{i} ^ n \sum_{j} ^ i [i, j] - \frac{n(n+1)}{2} \\ & = 2 \sum_i ^ n i \sum_{k | i} \frac{k \phi(k) + [k = 1]}{2} - \frac{n(n+1)}{2} \\ & = \sum_{i = 1} ^ n i \sum_{k | i} k \phi(k) & 相互抵消 \\ & = \sum_{i = 1} ^ n \sum_{k = 1} ^ {\lfloor \frac{n}{i} \rfloor} (ik) k \phi(k) & 枚举 \frac{i}{k} \\ & = \sum_{i = 1} ^ n i \sum_{k = 1} ^ {\lfloor \frac{n}{i} \rfloor} k ^ 2 \phi(k) \end{aligned}$ .

  设 $f(i) = i ^ 2 \phi(i), F(n) = \sum_{i \le n} f(i)$ , 现在要求 $\sum_{i = 1} ^ {n} i F(\lfloor \frac{n}{i} \rfloor)$ , 即考虑怎么计算 $F(n)$ .

  尝试构造函数 $g$ , 满足能够快速计算 $g$ 的前缀和以及 $(f * g)$ 的前缀和, 那么我们就可以进行杜教筛.

  将 $(f * g)$ 展开看看: $(f * g)(n) = \sum_{d | n} d ^ 2 \phi(d) g(\frac{n}{d})$ .

  我们知道 $n = \sum_{d | n} \phi(d)$ , 尝试使 $d ^ 2 g(\frac{n}{d})$ 与 $d$ 无关.

  那么令 $g(d) = d ^ 2$ 即 $g = id_2$ , 推导得 $f * id_2 = id_3$ , 所以 $F(n) = \sum_{i = 1} ^ n i ^ 3 - \sum_{i = 2} ^ n i ^ 2 F(\lfloor \frac{n}{i} \rfloor)$

  小结

  1. 自然数幂求和

  $\sum_{k = 1} ^ n k = \frac{n(n+1)}{2}$ .

  $\sum_{k = 1} ^ n k ^ 2 = \frac{n(n+1)(2n+1)}{6}$ .

  $\sum_{k = 1} ^ n k ^ 3 = (\sum_{k = 1} ^ n k) ^ 2$ .

  高阶的自然数幂求和考虑拉格朗日插值法.

  2. 处理 $\sum_{i = 1} ^ n \sum_{k | i} f(k)$ .

  思路1: 先枚举 $k$ , 再枚举 $i$ .

  思路2: 先枚举 $\frac{k}{i}$ , 再枚举 $k$ .

  3. $f(i) = i ^ k \phi(i)$ 的问题都可以用本题的方法解决, 可能需要结合自然数幂求和的相关知识.

 

杜教筛

标签:func   mem   zoj   构造   快速   前缀   bzoj   模型   时间   

原文地址:http://www.cnblogs.com/Sdchr/p/7623722.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!