Link.
Descripiton.
\((i,j)\in G\) 当且仅当 \(a_i\&a_j=0\)。
问图有几个连通块。
Solution.
这种题无法投机取巧,所以只能 \(O(2^n\cdot n)\) 这样的暴搜。
考虑怎么暴搜,新建一些辅助点,指向所有它的子集。
然后每次如果在新点,就减少 siz,否则就遍历它的补集。
Coding.
点击查看太菜代码
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
x=0;char c=getchar(),f=0;
for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}/*}}}*/
int n,m;char v1[1<<22],v2[1<<22];
inline void dfs(int x,int typ)
{
if((typ&&v2[x])||(!typ&&v1[x])) return;
if(!typ) return v1[x]=1,dfs(((1<<n)-1)^x,1);
v2[x]=1,dfs(x,0);for(int i=1<<n;i;i>>=1) if(x&i) dfs(x^i,1);
}
int main()
{
read(n,m);for(int i=0;i<(1<<n);i++) v1[i]=1;
int cnt=0;for(int i=1,x;i<=m;i++) read(x),v1[x]=0;
for(int i=0;i<(1<<n);i++) if(!v1[i]) dfs(i,0),cnt++;
return printf("%d\n",cnt),0;
}