Codeforces 1615B And It's Non-Zero 题解
题目传送门:
洛谷
CF
思路
暴力思路
要让所有元素按位与的结果不为 \(0\),就要让所有元素在二进制的某一位都为 \(1\)。
所以我们可以枚举每个二进制位,看看有几个 \(0\),求出最小值就是答案。
目前代码:
云剪贴板。当我提交的时候,发现提交记录,全 T 了。
优化
我们先来看看为什么会这样:这个算法的时间复杂度是 \(O(\sum r - l + 1)\)。对于数据来说,已经到了 \(2 \times 10^9\) 量级,当然会 TLE。我们想到:求的其实是多个区间和的最小值。一想到区间和,就想到用到前缀和。所以,我们可以用 \(sum_{i,j}\) 表示 \(1 \sim i\) 中二进制的第 \(j\) 位上有几个 \(1\)。先预处理一下,算出前缀和数组,最后计算的时候只需要枚举每一个二进制位,时间复杂度是 \(O(t)\)。
最终代码:
#include <iostream>
#include <algorithm>
using namespace std;int sum[200010][20];//前缀和数组,最大为log(2e5)=18
int main (){for (int i = 1; i <= 2e5; i++){int a[20] = {};//a[i]表示二进制的第i位int t = i , cnt = 0;while (t){a[++cnt] = t & 1;t = t >> 1;}for (int j = 1; j <= cnt; j ++)sum[i][j] = sum[i-1][j] + a[j];}int t;cin >> t;while (t--){int l , r;cin >> l >> r;int mx = 0;for (int i = 1; i <= 20; i ++)//枚举每一个二进制位mx = max(mx , sum[r][i] - sum[l-1][i]);cout << r - l + 1 - mx << endl;//通过0的个数求1的个数}
}