51Nod 1315 合法整数集

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

解释:
一开始没看懂,写暴搜来着,后来写残了,看了一下讨论区,发现是找对或运算贡献值最小的那个数。
详细解释就是,首先可以淘汰掉数组中比X更大的那些值。
然后对比X小的那些数计算对或运算的贡献值,可以发现,如果X中的某一位为0,而数组中的数字的对应位是1的话,肯定不能异或出X,所有这种情况也可以不考虑;
最后统计对异或值贡献最小得值即可。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MAXN 100
LL bit[MAXN];


LL maxIndex=1;
void run(LL x)
{
    LL index=1;
    while(x)
    {
        bit[index++]+=x%2;
        x/=2;
        maxIndex=max(maxIndex,index-1);
    }
}


int main()
{
//    freopen("in.txt","r",stdin);
    LL n,m;
    LL d;
    cin>>n>>m;
    for(LL i=1;i<=n;i++)
    {
        cin>>d;
        if((d|m)>m)continue;
        else
        {
            run(d);
        }
    }
    LL w=m;
    LL l=1;
    LL minDel=0x3f3f3f3f;
    while(w)
    {
        if(w%2)minDel=min(minDel,bit[l]);
        w/=2;
        l++;
    }
    cout<<minDel<<endl;
}
posted @ 2018-04-20 20:18  Bryce1010  阅读(100)  评论(0编辑  收藏  举报