AND Graph

You are given a set of size mm with integer elements between 00 and 2n−12n−1 inclusive. Let's build an undirected graph on these integers in the following way: connect two integers xx and yy with an edge if and only if x&y=0x&y=0. Here && is the bitwise AND operation. Count the number of connected components in that graph.

Input

In the first line of input there are two integers nn and mm (0≤n≤220≤n≤22, 1≤m≤2n1≤m≤2n).

In the second line there are mm integers a1,a2,…,ama1,a2,…,am (0≤ai<2n0≤ai<2n) — the elements of the set. All aiai are distinct.

Output

Print the number of connected components.

Examples

Input

2 3
1 2 3

Output

2

Input

5 5
5 19 10 20 12

Output

2

题意:每个数当成一个点,对于任意两点,若x&y==0,则x和y连一条边。最后求图中有几个联通块。

分析:显然与二进制关系很大,找二进制联系是难点。假设x(2)=001001100,x&y=0则y=_ _0_ _00_ _即x中为1的位置y中都为0,x中为0的y中01都可以。如果做一下z=x^111111111,即z=110110011,这样的话,z以及z的所有“子集”都可以与x连一条边,这个子集是说z中任意多个1换成0后的数,如何枚举子集呢?添加一个判重数组,写个循环把z的每个1换成0得到z’,再继续递归,以同样的方法把z’的每个1换成0,这样不重不漏地枚举完所有可以与x相连的数字。并且对于每个z,z’及其子集们,如果发现有题中的其他数,那么再以同样的方法枚举与其相连的集合。因此一次dfs可以找出完整的一个连通分量。

#include<bits/stdc++.h>
using namespace std;
#define all_bits ((1<<n)-1)

int n,m,a[1<<23],cnt;
bool have[1<<23],vis[1<<23];

void dfs(int x)//x及x的子集均可被点连 
{
	if(vis[x])return;
	vis[x]=1;
	if(have[x])dfs(x^all_bits);
	for(int i=0;i<n;i++)
	{
		if(1<<i & x)dfs(x ^ 1<<i);
	}
}

int main()
{
	//freopen("input.in","r",stdin);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>a[i];
		have[a[i]]=1;
	}
	for(int i=1;i<=m;i++)
	{
		if(!vis[a[i]])
		{
			cnt++;
			vis[a[i]]=1;
			dfs(a[i]^all_bits);
		}
	}
	cout<<cnt<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Wen_Yongqi/article/details/86507101