CF1516C 题解
提速偷懒小技巧
使用 bitset 自带的位运算配上 01 背包,真是又快速又省代码长度!
思路
首先设 ,若 ,显然最开始就是好的,不用删;否则可以先用 01 背包判断是否存在子序列之和为 的,如果不存在,说明最开始也是好的,也不删。
否则,我们只要设 表示每个 都除得尽的最大的 ,这时只要删去任意一个 的数即可使 。
本人喜欢使用位运算,如果代码看不懂我会在注释中写等价代码。
代码
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
int n, sum, a[105], g = 2048;
bitset <2000005> dp;
int main () {
ios::sync_with_stdio (0);
cin.tie (0);
cout.tie (0);
cin >> n;
for (int i = 0; i < n; ++ i)
cin >> a[i], sum += a[i];
if (sum & 1) { //奇数
cout << 0;
return 0;
}
dp[0] = 1;
for (int i = 0; i < n; ++ i)
dp |= dp << a[i]; //bitset 自带的位运算,用法详见 OI-wiki
if (! dp[sum >> 1]) { //没有 sum 的一半
cout << 0;
return 0;
}
for (int i = 0; i < n; ++ i)
sum = min (sum, a[i] & -a[i]); //lowbit 算法
for (int i = 0; i < n; ++ i)
if (a[i] & sum) { //如果 a[i] / sum % 2 = 1,则 a[i] 的二进制位上一定有 sum 这一位,否则没有
cout << "1\n" << i + 1;
return 0;
}
cout << -1;
return 0;
}

浙公网安备 33010602011771号