51nod 1315 合法整数集问题(预处理)

来源:互联网 发布:显卡升级软件下载 编辑:程序博客网 时间:2024/06/05 15:39

1315 合法整数集

一个整数集合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

题解:这是一道二进制的题目,只要想到二进制数如果某一位的1无法出现那么这个数就凑不出来的原理。将集合里的所有元素化为二进制然后加起来就知道每一位1出现的次数arr[i],这样只要对x的二进制每一位做一个询问,如果是1的话,尝试将集合中所有可能出现1的数删掉,也就是arr[i]的值,如果是0,则是删掉n-arr[i]个数,然后一直取最小就是答案。数据处理时候要注意在x某位为0的时候,如果该元素为1则删掉,不要加入统计的总数中,考虑例子x=101,有两个元素为111,001就明白了。

代码:
#include<iostream>#include<cstring>#include<math.h>#include<stdlib.h>#include<cstring>#include<cstdio>#include<utility>#include<algorithm>#include<map>using namespace std;typedef long long ll;const int Max = 1e6+5;const int mod = 1e9+7;const int Hash = 10000;const int INF = 1<<30;const ll llINF = 1e18;int n, x, cnt, counter;//cnt记录集合中元素的二进制位数,counter记录x的二进制位数int arr[40], temp[40], aim[40];void binary(int a){    while( a )    {        temp[cnt++] = a%2;        a /= 2;    }}int main( ){    //freopen("input.txt", "r", stdin);    while(~scanf("%d%d", &n, &x))    {        memset(arr, 0, sizeof(arr));        memset(temp, 0, sizeof(temp));        int k;        counter = 0;        binary(x);        counter = cnt;        memcpy(aim, temp, sizeof(int)*counter);//aim储存x的二进制序列        for(int i=0; i<n; i++)        {            scanf("%d", &k);            cnt = 0;            binary(k);            int flag = 0;            for(int j=0; j<cnt; j++)                if(aim[j]-temp[j] == -1)                    flag = 1;            if(flag)//这个元素不管怎么做或操作都不会和x相等,所以不要统计在内,否则会判断出错                continue;            for(int i=0; i<cnt; i++)                arr[i] += temp[i];        }        int ans = INF;        for(int i=0; i<counter; i++)        {            if(aim[i] == 1)                ans = min(ans, arr[i]);            else                ans = min(ans, n-arr[i]);        }        cout<<ans<<endl;    }    return 0;}


原创粉丝点击