很有趣的一道题.本来我是想考虑枚举选几个盒子,但我发现这样并没有对问题有任何简化.
然后就考虑容斥嘛...发现,这个容斥比较简单.
假如令
\(f(S)\)为
\(S\)集合中的玩具不能选的方案数.
那么答案就是:
\[\sum_{s\subseteq T}{(-1)^{|S|}f(S)}\] 那么
\(f(S)\)是啥呢?就是
\(2^{n-|S|}\).
然后直接套入就好.
怎么理解呢?
考虑容斥的基本形式:
答案=总方案数-不满足一个限制的方案数+不满足两个限制的方案数-不满足三个限制的方案数...
这不就是这个式子嘛....于是愉快
\(50pts\).
至于
\(n\)高达
\(10^6\)的时候,则需要使用
\(FMT\)(即高维前缀和)来处理.
\(70pts\)思路见代码后.
\(Code:\) #include #include #include #include #include #include #include #include #include #include #include
\(70pts\)并不难,
不过我们的容斥会有些许变化.
我们发现题目可以简化为:
给定
\(n\)个二进制数,任选一些数字,求有多少种选择方案使得选出来的数字按位or起来是每一位都是
\(1\).
于是我们就令
\(g(S)\)表示状态为
\(S\)的盒子的个数.
令
\(f(T)\)表示
\(\sum_{S\subseteq T}g(S)\).
那么不难想到有这样一个容斥:
\[\sum_{S\subseteq T}{2^{f(S)}(-1)^{m-|S|}}\] 那么我们考虑,这样求的复杂度怎么样.
计算
\(g(S)\)是和读入一起的,所以复杂度是
\(O(n*m)\)的.
而计算
\(f(T)\)呢?我们考虑这到底是个什么玩意儿.
这其实是状态为
\(T\)以及
\(T\)的子集的盒子总数.
所以我们要枚举子集的子集,这样的复杂度你可能会认为是
\(O(4^m)\)的
但其实不是,而是
\(O(3^m)\)的,这样的复杂度足以通过
\(70pts\).
满分思路见代码后.
\(Code:\) #include #include #include #include #include #include #include #include #include #include #include
我们发现上面的复杂度瓶颈其实是在求\(f(T)\)的时候我们需要枚举子集的子集.
那么我们就考虑能否优化掉这个复杂度.经过一番思考我们发现,这是个高维前缀和问题.
所以需要使用
\(FMT\),但这个题的
\(FMT\)没有你想象的那个长得像
\(FFT\)的亚子.
这个题目用到的
\(FMT\)是一种经典的形式:子集和形式.
这里用到的十分简单,不需要卷积形式..
然后你考虑,对于每一个集合,
我们如果都能算出来它在每一位上分别缺一个
\(1\)(即构成一个
\(size-1\)的子集)的方案数之和,
那么我们就能从
\(size\)为
\(1\)的子集一直递推到
\(size\)为
\(m\)的子集,于是我们就愉快的解决了这个问题.
\(Code:\) #include #include #include #include #include #include #include #include #include #include #include