• 杜教筛


    快速求一个积性函数 (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}).

    然后就可以筛了。

  • 相关阅读:
    对象的创建过程以及super关键字的使用
    Java语言基础
    数据结构-思考总结
    ssh简化登录
    WebStorm设置eslint保存自动格式化
    Jmeter简单使用
    nodemon添加babel支持
    VueCli 添加自定义组件报错
    shell写一个压测脚本
    Vue v-for指令中 key 的必要性
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10415764.html
Copyright © 2020-2023  润新知