卷积是个非常宽泛的概念,通常来讲,都是指泛函分析里面的卷积,知乎有篇 @马同学 写的介绍卷积的文章相当不错:
不过与通俗的卷积不同,我们这里要讲的是子集上的卷积(毕竟我们的研究对象一直都是集合)。
子集卷积(subset convolution)与覆盖积(cover product)
定义:两个函数 的子集卷积运算定义为一个函数 ,满足对于 ,有, 等价得我们可以定义为 。画个图解释一下:
覆盖积与子集卷积很类似,唯一的不同在于,覆盖积不要求 。
定义:两个函数 的覆盖积运算定义为一个函数 ,满足对于 ,有,。同样画个图解释一下(这画工真是太差了!):
子集卷积和覆盖积的应用非常广泛(以后我会讲一些应用),特别是很多图论问题(怕是我只会一丢丢图论)。
快速子集卷积与覆盖积
让我们来思考一下,如何计算出来子集卷积或者覆盖积。本着暴力美学(乱搞)的态度,直接枚举子集,那么我们就能在 内计算出子集卷积来,能在 计算出覆盖积来,这真是太慢了!
我们知道,通常的卷积运算,是可以利用快速傅里叶变换来加速的,将卷积形式变换为乘积形式,所以类比之下,我们考虑是否能有一种变换,能把子集卷积或者覆盖积变换为乘积形式。
为了方便起见,我们先定义一下逐点乘积(pointwise product):
定义:对于两个函数 而言,我们定义他们的逐点乘积为一个函数 ,满足对于任意 有, 。显然这是能在 时间内计算完成的。
定理10:覆盖积的zeta变换等于zeta变换的逐点乘积,即: 。
证明:对于 ,我们有:证毕。
这个非常漂亮简捷的结论,允许我们在 的时间内计算出覆盖积的zeta变换的所有 个值(这是因为由定理9,zeta变换的计算是在 的时间内),从而我们可以再通过定理8,利用再做一次Mobius变换,从而得到 。(即利用了 )。所以我们得到以下定理:
定理11:对于两个函数 ,如果给出了 和 总共的 个输入值,那么覆盖积 的所有 个值可以在 的时间内计算得到。
对于子集卷积,我们需要先按照 的大小进行分类再计算,我们令, 其中 表示,如果 则为 ,否则为 。
接下来我们稍稍推导一下: 于是我们就能用覆盖积来解决子集卷积啦。所以我们得到以下定理:
定理12:对于两个函数 ,如果给出 和 总共 个输入值,那么子集卷积 的所有 个值可以在 的时间内计算得到。