题解 P6442 【[COCI2011-2012#6] KOŠARE】
update: 修正了几个明显的问题(
容斥 + sos dp
如果你不会 sos dp
首先发现
于是问题转化为选若干个数使它们按位或为全集
继续转化一下,把每个箱子取个反,问题就变成了选若干个书使它们按位与为空集
接下来考虑 dp
有方程:
方程中
注意这里与标准 sos dp 方程
计算出来
答案要求按位与为空集,考虑容斥,全集即为
对于一个状态
于是这道题就被做完了,时间复杂度
code:
#include<bits/stdc++.h>
#define MAXN 1<<23
#define p 1000000007
using namespace std;
int n,m,ans;
int f[MAXN],pw[MAXN];
int main(){
pw[0]=1;
for(int i=1;i<(1<<22);i++)pw[i]=(pw[i-1]+pw[i-1])%p;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int k;scanf("%d",&k);
int st=(1<<m)-1;
while(k--){
int x;scanf("%d",&x);
st^=(1<<(x-1));
}f[st]++;
}
for(int i=1;i<=m;i++)
for(int mask=0;mask<(1<<m);mask++)
if(mask&(1<<(i-1)))
f[mask^(1<<(i-1))]=(f[mask^(1<<(i-1))]+f[mask])%p;
for(int mask=0;mask<(1<<m);mask++){
int sgn=1;
for(int i=1;i<=m;i++)
sgn=(mask&(1<<(i-1)))?-sgn:sgn;
ans=(ans+(pw[f[mask]]-1)*sgn)%p;
}printf("%d",(ans+p)%p);
return 0;
}