51nod-【1315 合法整数集】

来源:互联网 发布:.club域名与.com 编辑:程序博客网 时间:2024/06/05 05:04
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 712478
Output示例

2

One

对于这种题目,我真是忍无可忍,可以想象我是最后2个数据一直过不了,即直接下载下来
才知道有2种情况没有考虑,开始写题解
进行或运算全是0才为0
对于一个集合是否存在子集合或运算等于x,可以肯定大于x的数都不用考虑
对于x某个二进制为0,与之相对应的该数的这一位也应该为0,又一次进行筛选
我们只需要考虑x某个二进制为1,那么剩下的数对应为也应该为1(最起码有一个为1)
我们统计最少的1,即使需要删除的个数
下面还有2种情况,1、那就是有可能剩下的筛选出来的数本身就不能组合成x,那就是0
2、剩下的数没有一位和x化成二进制是等数位的那种情况肯定也是0
对于这2种情况我是用 if(sum==10000||max<len)进行判断的

别看我的代码不短,但是时间和大部分人都是一样的15MS

<span style="font-size:18px;">#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long longLL num[60],count2[600]; LL ans[600],flag[600]; int main(){LL n,x;while(~scanf("%lld%lld",&n,&x)){LL i;memset(count2,0,sizeof(count2));memset(flag,0,sizeof(flag)); for(i=0;i<n;++i)scanf("%lld",&num[i]);sort(num,num+n);LL pos=upper_bound(num,num+n,x)-num; LL len=0;while(x){ans[len++]=x&1; x>>=1;}LL dex=0,n2,k;for(i=0;i<pos;++i,dex=0){n2=num[i]; while(n2){k=n2&1;if(ans[dex]==0&&k){flag[i]=1;//代表已经筛去 break; } n2>>=1;++dex;} }dex=0;LL max=0;for(i=0;i<pos;++i,dex=0){if(!flag[i]){n2=num[i];while(n2){++dex; k=n2&1;if(k)count2[dex]++;n2>>=1;if(dex>max)max=dex;//记录最大数位 } } }LL sum=10000; for(i=1;i<=max;++i){if(count2[i]&&count2[i]<sum)sum=count2[i];}if(sum==10000||max<len)printf("0\n"); elseprintf("%lld\n",sum); } return 0;} </span>
Two
这是网上的代码,和我的思路是一样的,就是别人比我少了20行,但是运行时间一样
可以看看这个,写的很好 
<span style="font-size:18px;">#include<cstdio>#include<cstring>int num[60];int digitx[100],digitnum[100]; int main(){int n,x;while(~scanf("%d%d",&n,&x)){int i,len=0,nx=x;memset(digitnum,0,sizeof(digitnum)); for(i=0;i<n;++i)scanf("%d",&num[i]);while(nx){digitx[len++]=nx&1;nx>>=1; } int dex;for(i=0;i<n;++i){if((num[i]|x)>x)continue; dex=0; while(num[i]) { digitnum[dex++]+=num[i]&1; num[i]>>=1;  } }int sum=50;for(i=0;i<40;++i){if(digitx[i]&&!digitnum[i]){ sum=0; break;} if(digitx[i]){sum=digitnum[i]<sum?digitnum[i]:sum; } }printf("%d\n",sum); } return 0;} </span>


0 0
原创粉丝点击