神秘技巧:O(n lnln n) 的dirichlet卷积

要求其中一个是积性函数,另一个可以任意。

其实就是在质因数分解的意义下做高维前缀和。

高维前缀和

对于二维前缀和,我们也许可以直接推 s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]

而我们也可以

s[i][j]=s[i][j-1]+a[i][j]

然后

s[i][j]=s[i-1][j]+a[i][j]

以实现二维的前缀和。

换句话说我们可以先枚举维,然后对每一维做前缀和。

这里咋做

我们设 f 是那个积性函数,g 是任意的。

首先我们枚举“维”。维是啥?自然就是每个质数

注意到一个积性函数在 p1,p2...pk 处的值是不确定的。我们需要枚举它,相当于钦点 p 的次数。然后做一个如下操作:

g(i)×f(pk)g(i×pk)

注意到这里钦点 pk 是指恰好 f 那里的 p 就是 k 次。所以我们需要倒着枚举 i,类似背包的考虑,否则会导致重复贡献。

然后就枚举质数 p,倒着枚举 i,枚举 pk,做一个前缀和就行了。

这样的复杂度据说是 O(nloglogn) 的。实际跑出来也比 O(nlnn) 快很多。

特殊情况

如果 f 是完全积性函数,那你只需要这样做:

for(p: primes)
{
    for(int i=1;i<=n/p;++i)
    {
        g[i*p]+=g[i]*f[p];
    }
}

同样是 O(nloglogn) ,常数略小些。

posted @   Flandre-Zhu  阅读(134)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示