小红这天来到了三途川,发现这里有一个摆渡人,名字叫小町。小町的职责是将一些灵魂运送到冥界。每个灵魂有一个特性,用整数$a_i$表示。但小町非常喜欢偷懒,她只想运送尽可能少的灵魂然后摸鱼。
已知当船上所有灵魂特性的 位与运算 正好等于$0$时,船才可以开动。小町想让小红帮忙抛弃掉尽可能多的灵魂(但不能全抛弃),这样自己才能最大限度的偷懒。请你帮小红计算出可以抛弃的灵魂的最多数量。
输入描述
本题有多组数据,每组第一行一个整数$n$,表示灵魂数量;第二行$n$个整数$a_i$表示灵魂特性($0\leq a_i\leq n$)。
输出描述
对于每组测试数据,输出一行一个整数表示答案。
如果无解,请输出-1。否则输出一个整数,代表小町可以抛弃的最多灵魂数量。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13
| 输入 复制 2 5 7 3 3 2 5 5 2 14 6 30 10 输出 3 -1 说明 第一个测试数据,抛弃掉前三个灵魂,剩下的两个灵魂与运算恰好为0(2 & 5 = 0),因此船可以开动。 第二个测试数据,显然无论如何,船都是不能开动的。
|
解题思路
换句话说,要选择尽可能少的数,使得他们相与为0,即保证二进制的每一位至少包含1个0;
由于数据最大不超过127,令a[i] = 127 - a[i]
,那么问题转化为选择尽可能少的数,使得1能覆盖整个二进制所有数位。
可以通过DFS暴力枚举所有数字选和不选,但是显然可以进行很多剪枝优化:
AC代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include <iostream> #include <cstring> #include <algorithm> #include <vector>
using namespace std;
const int N = 2e5 + 10,M = 1 << 7;
int n,t; int a[N]; vector<vector<int>> col(7); int log2[M];
int lowbit(int x) { return x & -x; }
int h(int state) { int res = 0; for(int i = (1 << 7) - 1 - state; i ;i -= lowbit(i)) { int c = log2[lowbit(i)]; ++ res; for(auto row : col[c]) i &= ~row; } return res; }
bool dfs(int depth,int state) { if(!depth || h(state) > depth) return state == (1 << 7) - 1; int t = -1; for(int i = (1 << 7) - 1 - state; i; i -= lowbit(i)) { int c = log2[lowbit(i)]; if(t == -1 || col[c].size() < col[t].size()) t = c; } for(auto row : col[t]) if(dfs(depth - 1,state | row)) return true; return false; }
int main() { scanf("%d", &t); for(int i = 0; i < 7; ++ i) log2[1 << i] = i; while(t--) { for(int i = 0; i < 7; ++ i) col[i].clear(); scanf("%d", &n); for(int i = 1; i <= n; ++ i) { scanf("%d", &a[i]); a[i] = (1 << 7) - 1 - a[i]; for(int j = 0; j < 7; ++ j) if(a[i] >> j & 1) col[j].push_back(a[i]); } for(int i = 0; i < 7; ++ i) { sort(col[i].begin(),col[i].end()); col[i].erase(unique(col[i].begin(),col[i].end()),col[i].end()); } int depth = 0; while(depth <= n && !dfs(depth,0)) ++depth; int ans = n - depth; if(depth > n) ans = -1; printf("%d\n",ans); } return 0; }
|