高维前缀和
给一个 intrada 性质的问题:
求
这个形式看起来会很像一个 and-convolution,虽然并不完全是但这很重要。有个经典的朴素做法是以 枚举子集,从这个做法可以看出,,其中 有 个 off-bits,会被 次计算。
到了这个时候网上的脑瘫博客就会开始告诉你二维怎么办?容斥!三维不想推怎么办?分维前缀和! 维怎么办?看代码。
事实上分维前缀和的思想的确非常重要,如果有人看这篇博客推荐先理解。
我们首先对 sum over subsets 问题和高维前缀和之间的关联建立认知。一个 multidimensional partial sums 具体是在一个 -d 空间里求出向量 的所有元素的运算结果,也就是说我们用 这样一个向量来刻画问题的背景;而 sum over subsets 的一个 alternative ver. 则是给定 个物品及其价值,询问全集的某个子集的所有子集的价值和的价值和,以及我们只需要 就可刻画问题的背景(所有维度的有意义长度均为 ,即选与不选),而传统的 sum over subsets 则是给出全集所有子集的价值,询问全集的某个子集的所有子集价值和(即将某个子集的价值从由子集中的元素的价值决定到和子集中的元素的价值没关系)。
然后开始想象,typical sum over subsets problem 是在一个 -d 空间中做高维前缀和做的事情,所以我们可以类比得出其解法,并且我们得出结论:typical sum over subsets problem 是 multidimensional partial sums problem 的弱化,区别在于每一维度的模长是 还是任意。
应该比网上大部分博客都要清楚,或者更接近本质吧。不过我觉得这个洞见显然不是 SOS 的本质。
for (int i=0; i<k; ++i) {
for (int j=0; j<(1<<k); ++j) {
if ((j>>i)&1) f[j] += f[j^(1<<i)]; // 相当于从于第 @i 维的 0 转移到 1
}
}
dirichlet partial sums
这个东西就是上述问题的一个演绎应用,问题背景是:
已知数论函数 ,求 。
的做法应该都会。
会发现这个的形式和上面的很像,不过直接套会有一个 trap。如果你想的是把数分解为 的形式后考虑一个 -d 空间是不行的,因为 SOS 的维度模长为 ,所以应该考虑一个 -d 的空间。复杂度是 ,dyh 有个高妙的证法,但是我忘了,就这。
for (int i=1; i<=tot; ++i) {
for (int j=/*lower bound, depends on the specific problem*/; j<=n/prime[i]; ++j) {
f[j*prime[i]] += f[j];
}
}
当然这个有四个形式,不过很搞笑罢了,就是因数倍数乘上正着求和逆着求,本质都一样。
e.g.
看两道题。
第一个就是 codeforces - 585e,这个题求 的部分我是直接上的莫反,结果只能调和级数,翻了下题解发现式子里面的 直接没了,感觉很神奇,有空再想想。
第二个是 codeforces - 449d,一样的套路。记 为子集 AND 和为 的方案数,根据莫反的套路设出 为子集 AND 和是 超集的方案数。如果我们能求出 表示 的超集数量,则 ,然后通过逆 sos 跑差分就行了,注意这里是高维后缀和。
从这两道题我们可以洞见 sos 和莫反有着莫大的关联,之前陀螺仪在 oj 指出过,现在才理解一点点,果然还是要看太阳神的。
之前也看到有人写出莫反不关于莫比乌斯函数的形式,有空 cancan。
gugugu……
[TODO]:莫反不关于莫比乌斯函数的形式;FMT;gcd-convolution。