1315 合法整数集(位运算+模拟)

Posted Veritas des Liberty

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1315 合法整数集(位运算+模拟)相关的知识,希望对你有一定的参考价值。

题目来源: TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
技术分享 收藏
技术分享 关注
一个整数集合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

 

#include<bits/stdc++.h>
#include<cstdio>
const int maxn = 55;
const int M = 0x3f3f3f3f;
using namespace std;

int a[maxn];
int vis[maxn];
int dis[maxn];
int logo[maxn];
int k[maxn];
int i,j;
int main()
{
	int n,x;
	while(scanf("%d %d",&n,&x)!=EOF)
	{
		int ans = 0;
		memset(vis, 0, sizeof(vis));
		while(x)
		{
			vis[ans++] = x%2;
			x /= 2;
		}
		memset(logo, 0, sizeof(logo));
		memset(dis, 0, sizeof(dis));
		memset(k, 0, sizeof(k));
		for(i=0; i<n; i++)
		{
			scanf("%d",&a[i]);
			int flag = a[i];
			int d = 0;
			while(flag)
			{
				dis[d++] = flag % 2;
				flag /=2;
				if(dis[d-1] && !vis[d-1])
					logo[i] = 1;
			}
		}
		int num = M;
		for(i=0; i<n; i++)
		{
			if(logo[i])
				continue;
			int flag = a[i];
			int d = 0;
			while(flag)
			{
				k[d++] += flag%2;
				flag /= 2;
			}
		}
		for(i=0; i<ans; i++)
		{
			if(!vis[i])
				continue;
			num = min(k[i],num);
		}
		if(num == M)
			printf("%d\n",0);
		else
			printf("%d\n",num);
	} 
	return 0;	
} 

  

 

这道题的思路不难,我的做法是利用or操作对位的影响。
想一下,如果我们把几个二进制数or起来,我只要某一个数在某一位是1,那么结果的这一位就一定是1。
下面举例说明解法:
比如Y={1,2,4,8}     X=7
即 Y:1,10,100,1000    X:111
我们先排除掉那些把它们加入or式中一定会出现!=X的数字,这些数字满足(a|X)==X,也就是说如果一个数字,它的某一个位是1,而对应X的那一位是0,则无论这个数和谁相或,结果都一定不会等于X了。我们先从Y集合中去掉这些数,因为这些数恰恰是无论如何都不可能被去掉的,研究它们没有意义。这里去掉1000
然后,统计X的每一个1位对应Y中是1的有几个:
X:1    1     1
    100   10     1
如果我们把Y改为{1,11,100}
那么
X:1           1        1       
    100       11     1、11
我们要向使得任意子集相或都不为X,方法只有一个,那就是破坏掉X的一个1位,这样无论怎么组合都不会==X了,相反如果每一位都有数字保证,那么一定能组合出X。

 

以上是关于1315 合法整数集(位运算+模拟)的主要内容,如果未能解决你的问题,请参考以下文章

51 NOD 1315 合法整数集(思维 + 模拟)

1315 合法整数集

51Nod 1315 合法整数集

51nod-1315合法整数集(数位)

PAT-求符合给定条件的整数集

LaTex如何输入数集符合(整数集,实数集,复