51Nod_1315 合法整数集【位运算】

                                        51Nod_1315 合法整数集

                                   http://www.51nod.com/Challenge/Problem.html#!#problemId=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.

输入

第一行两个整数N,X,其中N为Y集合元素个数,X如题所述,且1<=N<=50,1<=X<=1,000,000,000.之后N行,每行一个整数yi,即集合Y中的第i个元素,且1<=yi<=1,000,000,000.

输出

一个整数,表示最少删除多少个元素。

样例输入

5 7
1
2
4
7
8

样例输出

扫描二维码关注公众号,回复: 5047467 查看本文章
2

分析

设x=a1 | a2 |……| an。|是或运算符号。那么任意一个ai不可能在x为0的二进制位处为1,一旦存在这样的ai,它们的或运算值一定不等于x。它们是不必删除的,因为一旦使用它们,其值一定不等于x。该如何识别出这类数呢?看看这个条件 (x|ai)>x,如果ai的某个二进制位为1而x对应的二进制位为0,那么ai就是此类数。通过这种方法标记这类数,不用去考虑它们。除了这一类数,剩下的都是由x的某些为1的二进制位变为0形成的,现在就要统计x为1的二进制位有多少数可以提供,例如1、2、4,8,X=7,8是不必删除的数,不用考虑,1,2,4,7的二进制分别为001、010、001和111。遍历x的各个为1的二进制位,统计对应二进制位也为1的数的个数,最少个数就是答案,统计结果为111,因此答案为1。具体看程序

C++程序

#include<iostream>

using namespace std;

const int N=60;
int a[N];
bool flag[N]; 

int main()
{
	int n,x;
	scanf("%d%d",&n,&x);
	for(int i=0;i<n;i++)
	  scanf("%d",&a[i]);
	for(int i=0;i<n;i++)
	  if((x|a[i])>x)
	    flag[i]=true;
	int ans=n;
	for(int t=1;t<=x;t*=2)
	  if((x&t)==t)//如果这位是1 
	  {
	  	//统计该位是1的个数 
		int num=0;
		for(int i=0;i<n;i++)
		{
			if(!flag[i]&&(a[i]&t)==t) num++;
		} 
		if(num<ans)
		  ans=num;
	  }
	printf("%d\n",ans);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/SongBai1997/article/details/86616996