一个整数集合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
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 long
LL 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");
else
printf("%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>