积性函数的筛法

本文介绍了数论中积性函数的筛法,包括欧拉筛、杜教筛和Min_25筛等,这些方法能有效地计算积性函数的前缀和,特别是线性复杂度的欧拉筛适合处理所有积性函数。文章还探讨了如何针对不同积性函数特点进行优化,并提供了实际应用的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面的所有知识均属数论范畴。


欧拉筛

可以做到 O ( n ) O(n) O(n)线性复杂度

可以筛所有的积性函数(即对于所有的 a ⊥ b a \perp b ab 都满足 f ( a b ) = f ( a ) ∗ f ( b ) f(ab) = f(a)*f(b) f(ab)=f(a)f(b) 的函数)。

举两个例子:

线性筛欧拉函数:

inline void Sieve()
{
   
    phi[1] = 1;
    for(register int i = 2; i <= MAXN; i++)	//MAXN表示值域
    {
   
        if(!NotPrime[i])	//是质数
        {
   
            phi[i] = i - 1;
            Prime[++len] = i;
        }
        for(register int j = 1; j <= len && i * Prime[j] <= MAXN; j++)
        {
   
            NotPrime[i * Prime[j]] = true;
            if(i % Prime[j] == 0)	//此时 Prime[j] 为 i 的最小质因子
			{
   
            	phi[i * Prime[j]] = phi[i] * prime[j];
				break;
            }
            phi[i * Prime[j]] = phi[i] * (Prime[j] - 1);
        }
    }
    return;
}

线性筛莫比乌斯函数:

inline void Sieve()
{
   
    miu[1] = 1;
    for(register int i = 2; i <= MAXN; i++)
    {
   
        if(!NotPrime[i])
        {
   
            miu[i] = -1;
            Prime[++len] = i;
        }
        for(register int j = 1; j <= len && i * Prime[j] <= MAXN; j++)
        {
   
            NotPrime[i * Prime[j]] = true;
            if(i % Prime[j] == 0) break;	//此时 miu 函数值为 0,可以直接跳过
            miu[i * Prime[j]] = -miu[i];
        }
    }
    return;
}

可以发现,每个数最多只会被自己的最小质因子筛到一次,所以时间复杂度是线性的 O ( n ) O(n) O(n)

不过要注意,每个数被自己的最小质因子筛到时,对应的 i * Prime[j]仍然是需要计算函数值的!(当然 μ \mu μ 函数此时就等于 0 0 0,可以直接跳过)


杜教筛

在非线性时间内求解积性函数的前缀和。

设现在我们要求的是 f f f 的前缀和,即 S ( n ) = ∑ i = 1 n f ( i ) S(n) = \sum_{i = 1} ^n f(i) S(n)=i=1nf(i)

我们考虑把 f f f 卷上一个 g g g 的前缀和,即:
S ′ ( n ) = ∑ i = 1 n ( f ∗ g ) ( i ) = ∑ i = 1 n ∑ d ∣ i f ( d ) g ( i d ) = ∑ d = 1 n g ( d ) ∑ i = 1 ⌊ n d ⌋ f ( i ) = ∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) \begin{aligned} S'(n) &= \sum_{i = 1}^n(f * g)(i) \\ &= \sum_{i = 1} ^n \sum_{d | i} f(d)g(\frac{i}{d}) \\ &=\sum_{d = 1}^n g(d) \sum_{i = 1}^{\lfloor\frac{n}{d}\rfloor} f(i) \\ &=\sum_{d = 1}^ng(d)S(\lfloor\frac{n}{d}\rfloor) \end{aligned} S(n)=i=1n(fg)(i)=i=1ndif(d)g(di)=d=1ng(d)i=1dnf(i)=d=1ng(d)S(dn)
然后再推导一下,发现:
g ( 1 ) S ( n ) = ∑ d = 1 n g ( d ) S ( ⌊ n d ⌋ ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) g(1)S(n) = \sum_{d = 1}^ng(d)S(\lfloor\frac{n}{d}\rfloor) - \sum_{d = 2}^ng(d)S(\lfloor\frac{n}{d}\rfloor) g(1)S(n)=d=1ng(d)S(dn)d=2ng(d)S(dn)
即:
S ( n ) = ∑ i = 1 n ( f ∗ g ) ( i ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) g ( 1 ) S(n) = \frac{\sum_{i = 1}^n(f * g)(i) - \sum_{d = 2}^ng(d)S(\lfloor\frac{n}{d}\rfloor)}{g(1)} S(n)=g(1)i=1n(fg)(i)d=2ng(d)S(dn)
所以,只要我们找到合适的 g g g,就能够快速求出 S ( n ) S(n) S(n) 了。

(这个时候建议看看下文的莫反公式)

对于 μ \mu μ 的前缀和,我们发现有 μ ∗ 1 = ϵ \mu * 1 = \epsilon μ1=ϵ,即定义 g = 1 g = 1 g=1,代入公式有 S ( n ) = 1 − ∑ i = 2 n S ( n i ) S(n) = 1 - \sum_{i = 2}^nS(\frac{n}{i}) S(n)=1i=2nS(in)

对于 φ \varphi φ 的前缀和,我们发现有 φ ∗ 1 = i d \varphi * 1 = id φ1=id,即定义

### VSCode Vue3 开发常用插件推荐 #### 编辑增强类插件 为了提高编辑效率,一些插件提供了诸如自动补全、语法高亮等功能。例如 `Auto Rename Tag` 插件能够在修改HTML/XML标签时同步更新其闭合标签[^2]。 #### 主题与界面优化 对于视觉体验有需求的开发者来说,可以选择像 `Atom One Light Theme` 或者 `Cobalt2 Theme Official` 这样的主题来美化工作环境[^1]。另外还有 `VSCode Great Icons` 提供更美观的图标支持[^1]。 #### 中文语言包 为了让国内用户更好地理解和操作VSCode,安装 `Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code` 是很有必要的,它能够使整个IDE界面汉化。 #### 代码片段加速开发 `Vue VSCode Snippets` 和 `Vue 3 Snippets` 都是非常实用的选择,前者通过预设好的模板让开发者可以迅速构建起基本结构;后者则专注于为最新版本框架定制专属片段集合[^3]。 #### 导航辅助工具 当项目规模逐渐增大之后,利用 `Vue Peek` 实现快速定位组件定义位置变得尤为重要。该功能允许使用者仅需简单点击就能直达目标源码所在之处。 #### 路径处理解决方案 针对模块间相互引用频繁的情况,`Path Intellisense` 的存在无疑大大简化了这一过程——无论是相对还是绝对路径都能得到智能提示。而 `file-jump` 功能同样实现了别名路径下的便捷跳转[^4]。 #### 类型感知能力加强 考虑到TypeScript日益普及的趋势,在编写基于TSX/JSX语法糖封装后的单文件组件(SFCs)时,借助于 `TypeScript Vue Plugin (Volar)` 及 `Vue Language Features (Volar)` 来获得更好的类型推断效果显得尤为关键。 #### 图片资源管理 如果涉及到大量图像素材,则不可错过 `Image preview` ,它可以即时显示图片内容而不必离开当前窗口去寻找原图。 #### 版本控制集成 最后但并非最不重要的是,保持良好的Git实践习惯始终是软件工程领域内不可或缺的一环。因此建议加入 `SVN` 或其他形式的SCM客户端以便随时追踪变更记录并协同作业。 ```json { "editor.codeActionsOnSave": { "source.fixAll.eslint": true, "source.organizeImports": true }, "[vue]": { "editor.defaultFormatter": "Vue.vscode-vue-languageservice" } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值