本文主要是介绍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
样例输出
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;
}
这篇关于51Nod_1315 合法整数集【位运算】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!