问题模型
快速求(f(S) = sum_{A cup B = S} g(A)h(B))。
公式推导
原式等价与:
[ f(S) = sum_{A subseteq S} sum_{B subseteq S} [A cup B = S]g(A)h(B)
]
[ = sum_{A subseteq S} g(A) sum_{B subseteq S} h(B)[A cup B = S]
]
那么我们设:
[hat f(S) = sum_{T subseteq S} f(T)
]
[hat g(S) = sum_{T subseteq S} g(T)
]
[hat h(S) = sum_{T subseteq S} h(T)
]
就有:
[ hat f(S) = hat g(S) imes hat h(S)
]
之后可以用之前的子集反演得到:
[ f(S) = sum_{T subseteq S} (-1)^{|S-T|} hat f(T)
]
现在问题就是如何快速的在(hat f)与(f)之间变换。
由于(3^n)的枚举子集过于简单,就不讲了,在这里介绍(O(n2^n))的做法:
我们先考虑正变换,考虑递推:
设(hat f_{i}(S))表示(sum_{T subseteq S} [(S-T) subseteq {0,1,2,...,i}] f(T))
那么我们有:$ hat f_{0}(S) = f(S) (
然后对于所有**不包含**)i+1(这个元素的集合)S$,有:
[hat f_{i+1}(S) = hat f_{i}(S)
]
[ hat f_{i+1}(S cup {i+1}) = hat f_{i}(S cup {i+1}) + hat f_{i}(S)
]
那么(hat f_n)即为所求。
接下来我们考虑反演,求出答案:
我们类似的定义(f_{i}(S)),那么对于所有不包含(i)这个元素的集合(S),有:
[f_{i-1}(S) = f_{i}(S)
]
[ f_{i-1}(S cup {i}) = f_{i}(S cup {i}) - f_{i}(S)
]
最后(f_0)即为所求。
又因为每一位(每一个元素)是独立的,所以我们可以从(0 sim n)而不是从(n sim 0)。
那么我们就做完了。
拓展(_1):集合交卷积
这个也是可以做集合交卷积的。
因为(A cap B) = (All - (All-A) cup (All-B))
所以我们在进行变换之前先将每个值和它的补集交换一下,
在变换之后在交换一次,就好了。
拓展(_2):子集卷积
其实就是在并集的基础上有加了一个条件:(A cap B = Phi)。
这样我们只需要再加一维表示集合的大小,就好了。