LGP6442题解
和SP13106是双倍经验哦
我们首先发现 \(m=20\),所以一言不合先状压。
然后发现状压了之后我们实际上要求的是有多少个子集按位或的值为全集,相当于求有多少个子集按位与的值为 \(0\)。(把每个集合取反)
我们先不考虑“恰好为空”这个东西,我们考虑“一定包含空”这个东西。
一定包含一个集合 \(S\) 很明显预处理一个超集和就完了,用 FWT 是 \(O(m2^m)\) 的。
容易发现可以直接容斥,预处理一个 \(2\) 的幂就完了。
#include<cstdio>
#include<cctype>
typedef unsigned ui;
const ui M=1<<20|5,mod=1e9+7;
ui n,m,dp[M],ppc[M],pw2[M];
char buf[1<<25|1],*p=buf;
inline ui read(){
ui n(0);char s;while(!isdigit(s=*p++));while(n=n*10+(s&15),isdigit(s=*p++));return n;
}
signed main(){
ui i,j,k,ans;fread(buf,1,sizeof buf,stdin);n=read();m=read();pw2[0]=1;
for(i=1;i<=n;++i){
k=read();ans=0;pw2[i]=(pw2[i-1]<<1)%mod;while(k--)ans|=1<<read()-1;++dp[(1<<m)-1^ans];
}
for(i=1;i^1<<m;i<<=1)for(j=0;j^1<<m;j+=i<<1)for(k=0;k^i;++k)dp[j|k]+=dp[i|j|k];ans=0;
for(i=0;i^1<<m;++i)ppc[i]=ppc[i>>1]^(i&1),ans=(ans+(ppc[i]?mod-1ull:1ull)*(pw2[dp[i]]-1))%mod;printf("%u",ans);
}