码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-10-02 13:05:00      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:turn   ane   memset   file   lis   cpp   out   red   scan   

题目来源: 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 合法整数集(位运算+模拟)

标签:turn   ane   memset   file   lis   cpp   out   red   scan   

原文地址:http://www.cnblogs.com/ruruozhenhao/p/7619971.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!