有N名士兵(编号从1到N)。每个士兵都拥有M种不同技能的一些技能(编号从1到M)。军队的技能组合是其组成士兵的技能组合。有多少不同的士兵子集满足具有特定技能要求 Problem
根据解释问题减少到找到这些数字的子集的数量,其OR正好等于所需的值,例如请求
设f(i)为数j的数量,使得j OR i = i。然后答案是Σi(-1)^ popcount(i xor req)(2 ^ f(i) -1)对于所有i,我或者req是req
该公式是如何产生的以及popcount如何描述它的增加或减少。
答案 0 :(得分:0)
这是我的看法。解决问题的方法:而不是推理拥有某些技能的群体, 让我们理解那些没有某些技能的士兵 因为第二个属性从组传播到所有成员。
在我们开始之前,稍微简化一下:
在不失一般性的情况下,我们可以过滤掉至少有一项技能超出规定范围的士兵。因为子集的技能必须完全是所需的技能组合,所以永远不需要那些了解太多的聪明士兵。
从现在开始,我们假设所需的技能组合为{1, ... , R}
,并且士兵的技能介于1
和R
之间。
我们需要A_i
的定义(其中i
属于{1,..,R}
):
A_i
:在小组技能组合中具有i
技能的士兵组。
换句话说,A_i
中的一个群组(inter
表示交叉点)是一个至少有一名士兵拥有技能编号i
的群组。
现在是i<j
,
A_i inter A_j
=在小组技能组合中具有i
和j
技能的士兵小组。
换句话说,A_i inter A_j
中的一个群组是至少包含其中一个属性的群组
i
和j
的士兵。i
,一名技能j
。并且
A_1 inter A_2 ... inter A_R
是在他们的小组技能组合中具有技能1,.., R
的一组士兵。
问题所在的问题可以用A_i
表示:
A_1 inter A_2 ... inter A_R
的大小是多少?
等于
2^2^R - size( comp(A_1) union comp(A_2) ... union comp(A_R) )
其中comp(A)
是补充集。
现在,我们可以应用包含 - 排除原则。
还有一个技巧可以使它成为可计算的:
如果I
是{1,..,R}
的子集,则
intersection(comp(A_j) for all j in I)
是I
中没有技能(作为一个群体)的士兵群体。
请注意,这样一个群体中的士兵正是I
中没有任何技能的士兵。
我们将g(I)
定义为集合I
中没有任何技能的士兵数量。有了这个,我们有
size( intersection(comp(A_j) for all j in I) ) = 2^g(I)
最后,我得到的结果是:
2^2^R - sum( (-1)^(size(I)+1) * 2^g(I) , for each I subset of {1,..,R} and I non-empty)
我希望这会有所帮助。如果有些事情仍然不清楚,请告诉我。