Codeforces 1615B And It’s Non-Zero 题解
题目传送门:
思路
暴力思路
要让所有元素按位与的结果不为 0 0 0,就要让所有元素在二进制的某一位都为 1 1 1。
所以我们可以枚举每个二进制位,看看有几个 0 0 0,求出最小值就是答案。
目前代码:
优化
我们先来看看为什么会这样:这个算法的时间复杂度是 O ( ∑ r − l + 1 ) O(\sum r - l + 1) O(∑r−l+1)。对于数据来说,已经到了 2 × 1 0 9 2 \times 10^9 2×109 量级,当然会 TLE。我们想到:求的其实是多个区间和的最小值。一想到区间和,就想到用到前缀和。所以,我们可以用 s u m i , j sum_{i,j} sumi,j 表示 1 ∼ i 1 \sim i 1∼i 中二进制的第 j j j 位上有几个 1 1 1。先预处理一下,算出前缀和数组,最后计算的时候只需要枚举每一个二进制位,时间复杂度是 O ( t ) O(t) 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的个数
}
}

560

被折叠的 条评论
为什么被折叠?



