51nod 1315 合法整数集 (位操作理解模拟进制转换)
Posted 只有你
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 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 7
1
2
4
7
8
Output示例
2
首先找出经或操作后能合成x的整数a,在a的二进制表示下的数位值为1的数位属于在x的二进制表示下的数位值为1的数位的集合的子集。
然后用w[i]来存储不同数位的1的数量,取w[i]中的最小值即可。
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 #define INF 0x3f3f3f3f 5 int w[55]; 6 int vis[55]; 7 int valid[55]; 8 int x,n; 9 int a[55],b[55]; 10 int main() 11 { 12 ios::sync_with_stdio(false); 13 while(cin>>n>>x) 14 { 15 memset(valid,0,sizeof(valid)); 16 int pos=0; 17 while(x) 18 { 19 valid[pos++]=x%2; 20 x/=2; 21 } 22 memset(vis,0,sizeof(vis)); 23 memset(w,0,sizeof(w)); 24 for(int i=0;i<n;i++) 25 { 26 cin>>a[i]; 27 int tmp=a[i]; 28 int d=0; 29 while(tmp) 30 { 31 b[d++]=tmp%2; 32 tmp/=2; 33 if(b[d-1]&&!valid[d-1]) 34 vis[i]=1; 35 } 36 } 37 int ans=INF; 38 for(int i=0;i<n;i++) 39 { 40 if(vis[i]) continue; 41 int tmp=a[i]; 42 int d=0; 43 while(tmp) 44 { 45 w[d++]+=tmp%2; 46 tmp/=2; 47 } 48 } 49 for(int i=0;i<pos;i++) 50 { 51 if(!valid[i]) continue; 52 ans=min(w[i],ans); 53 } 54 ans=ans==INF?0:ans; 55 cout<<ans<<endl; 56 } 57 return 0; 58 }
注:数组开35的话,过不了最后一组用列,很迷。
以上是关于51nod 1315 合法整数集 (位操作理解模拟进制转换)的主要内容,如果未能解决你的问题,请参考以下文章