51nod 1315 合法整数集

一个整数集合S是合法的,指S的任意子集subS有Fun(SubS)!=X,其中X是一个固定整数,Fun(A)的定义如下:
A为一个整数集合,设A中有n个元素,分别为a0,a1,a2,...,an-1,那么定义:Fun(A)=a0 or a1 or ... or an-1;Fun({}) = 0,即空集的函数值为0.其中,or为或操作。
现在给你一个集合Y与整数X的值,问在集合Y至少删除多少个元素能使集合Y合法?

例如:Y = {1,2,4},X=7;显然现在的Y不合法,因为 1 or 2 or 4 = 7,但是删除掉任何一个元素后Y将合法。所以,答案是1.
Input
第一行两个整数N,X,其中N为Y集合元素个数,X如题所述,且1<=N<=50,1<=X<=1,000,000,000.
之后N行,每行一个整数yi,即集合Y中的第i个元素,且1<=yi<=1,000,000,000.
Output
一个整数,表示最少删除多少个元素。
Input示例
5 7
1
2
4
7
8
Output示例
2



思路:如果一个数的二进制某一位是1并且x的这一位是0,则这个数就不用管了,

然后所求的答案就是剩下的数中二进制中值和x一样都为1的个数的最小值;(有点讲的不清楚,直接看代码吧)



#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
#define esp  1e-8
const double PI = acos(-1.0);
const int inf = 1000000005;
const long long mod = 1000000007;
//freopen("in.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("out.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
int a[55], b[33], vis[55];
int main()
{
	int n, x, i, j;
	while (~scanf("%d%d", &n, &x))
	{
		for (i = 1; i <= n; ++i)
			scanf("%d", &a[i]);
		memset(b, 0, sizeof(b));
		int mm = 100;
		int s = 0;
		memset(vis, 0, sizeof(vis));
		for (i = 0; i <= 30; ++i)
		{
			if ((1 << i) > x)
				break;
			if (!((1 << i) &x))
			{
				for (j = 1; j <= n; ++j)
				{
					if (a[j] & (1 << i))
					{
						vis[j] = 1;
					}
				}
			}
		}
		for (i = 0; i <= 30; ++i)
		{
			if ((1 << i) > x)
				break;
			if ((1 << i) & x)
			{
				s += (1 << i);
				for (j = 1; j <= n; ++j)
				{
					if (((a[j] & (1 << i))) && (a[j] <= x) && !vis[j])
					{
						b[i] ++;					
					}
				}
				mm = min(mm, b[i]);
			}					
		}
		printf("%d\n", mm);
	}
}





你可能感兴趣的:(51nod 1315 合法整数集)