题目描述

从$n$个数中选出$n-k$个,使得它们的二进制或(or)最大。输出这个值。

输入

第一行包含两个正整数$n,k(2\le n\le 100000,1\le k\le 100,k<n)$,分别表示宝石的个数以及要扔掉的宝石个数。
第二行包含$n$个整数$w_1,w_2,...,w_n(0\le w_i\le 100000)$,分别表示每个宝石的魔力。

输出

输出一行一个整数,即最大的威力。

样例输入

4 1
32 16 8 7

样例输出

56


题解

乱搞+dp

由于上限为$100000$,因此最多只有$17$个二进制位。

考虑当可以保留的数的个数$n-k\ge 17$时,显然对于每一位选出一个该位为$1$的数,选出来的数一定不超过$17$个。因此一定能够占满所有的二进制位。所以所有的数的二进制或即为答案。

当$n-k<17$时,由于$k$只有$100$,所以$n$只有$117$,因此可以暴力dp。设$f[i][j]$表示能否选出$i$个数使得它们的二进制或为$j$。然后随便转移即可。

时间复杂度$O(117*17*2^{17})$。

#include <cstdio>
bool f[17][131080];
int main()
{
int n , m , i , x , ans;
scanf("%d%d" , &n , &m);
if(n - m >= 17)
{
ans = 0;
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , ans |= x;
printf("%d\n" , ans);
}
else
{
f[0][0] = 1;
int j , k;
for(i = 1 ; i <= n ; i ++ )
{
scanf("%d" , &x);
for(j = 0 ; j < n - m ; j ++ )
for(k = 0 ; k < 131072 ; k ++ )
f[j + 1][k | x] |= f[j][k];
}
for(i = 131071 ; ~i ; i -- )
if(f[n - m][i])
return printf("%d\n" , i) , 0;
}
return 0;
}

最新文章

  1. Hibernate入门与简谈
  2. js 求时间差
  3. 【leetcode】Same Tree(easy)
  4. Codeforces Round #341 (Div. 2)
  5. c#面向对象基础 静态成员、构造函数、命名空间与类库
  6. sm30表维护做排序
  7. Android四大组件之——Activity的生命周期(图文详解)
  8. SpringServletContext简单案例
  9. 深入理解 KVC\KVO 实现机制 — KVC
  10. 简单高效读写修改整个文本Slurp
  11. 写了交互给后台后来不能用?bug多多多又找不到文件效率低?工作流程帮你优化起来~~~~
  12. Hadoop2.3.0具体安装过程
  13. linux command----vi
  14. vue添加页面键盘事件
  15. curl模拟访问已经存在的cookie
  16. Cdnbest的cdn程序默认支持web Socket
  17. java框架篇---hibernate之连接池
  18. Python爬虫——小说
  19. 使用Python3.x抓取58同城(南京站)的演出票的信息
  20. 003_Java笔记3:Eclipse添加jar包

热门文章

  1. (第02节)集成Sping框架
  2. ELK初学搭建
  3. jQuery的封装
  4. 一些android的日常笔记
  5. Xshell4 出现Linux中中文字符乱码问题
  6. 强化记忆之php
  7. Python的jieba模块简介
  8. php安装php-redis扩展
  9. Leecode刷题之旅-C语言/python-35.搜索插入位置
  10. 6-C++远征之封装篇[上]-学习笔记