您的位置:首页 > 其它

51nod 1315

2016-09-13 21:12 183 查看
这题思维方面要求还是有的、

先把数划分为两种,一种是可能删去的,一种是不可能删去的,  不可能的数有两种 

第一种:如果一个数a|x>x那么a肯定不可能删去,因为含有它的子集根本|不到k, 

第二种:要|操作得到k,那么把k化为二进制比如 1011, 如果一个数是111,那个这个111就肯定是不可能删去的,它|之后会让第三位为1,也就不可能达到k、

那么把剩下的数也就是说将他们化为二进制,处理他们为1的部分++,   因为每一个数对应的每一位最多只有一个1, 那么再找一个最小数的个数行了、

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int qq = 55;
ll num[qq];
int vis[qq];
int flag[qq];
int main(){
int p=0;
ll n,k;scanf("%lld%lld",&n,&k);
int x;
for(int i=0; i<n; ++i){
scanf("%d",&x);
if((x|k)>k) continue; //首先处理掉第一种不可能删去的数、
num[p++] = x;
}
x=0;
while(k){
flag[x++]=k%2;
k/=2;
}
int w[50];
for(int i=0; i<p; ++i){
int y=0;
while(num[i]){
w[y++]=num[i]%2;
num[i]/=2;
}
int j;
for(j=0; j<y; ++j) //处理掉第二种不可能删除的数、
if(w[j]==1&&flag[j]==0) break;
if(j<y) continue;
for(j=0; j<y; ++j) //最后统计每一位上有1的数的个数、
if(w[j]==1) vis[j]++;
}
int maxn=1e9;
for(int i=0; i<x; ++i) //要删去最少的1,那么挑k中为1的位置中最小的一个统计数
if(flag[i]==1) maxn=min(maxn, vis[i]);
printf("%d\n", maxn);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: