B. And It's Non-Zero
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an array consisting of all integers from [l,r][l,r] inclusive. For example, if l=2l=2 and r=5r=5, the array would be [2,3,4,5][2,3,4,5]. What's the minimum number of elements you can delete to make the bitwise AND of the array non-zero?
A bitwise AND is a binary operation that takes two equal-length binary representations and performs the AND operation on each pair of the corresponding bits.
Input
The first line contains one integer tt (1≤t≤1041≤t≤104) — the number of test cases. Then tt cases follow.
The first line of each test case contains two integers ll and rr (1≤l≤r≤2⋅1051≤l≤r≤2⋅105) — the description of the array.
Output
For each test case, output a single integer — the answer to the problem.
Example
input
Copy
5 1 2 2 8 4 5 1 5 100000 200000
output
Copy
1 3 0 2 31072
Note
In the first test case, the array is [1,2][1,2]. Currently, the bitwise AND is 00, as 1 & 2=01 & 2=0. However, after deleting 11 (or 22), the array becomes [2][2] (or [1][1]), and the bitwise AND becomes 22 (or 11). This can be proven to be the optimal, so the answer is 11.
In the second test case, the array is [2,3,4,5,6,7,8][2,3,4,5,6,7,8]. Currently, the bitwise AND is 00. However, after deleting 44, 55, and 88, the array becomes [2,3,6,7][2,3,6,7], and the bitwise AND becomes 22. This can be proven to be the optimal, so the answer is 33. Note that there may be other ways to delete 33 elements.
-------------------------------------------------------------------------------------------------------------------------
意思是让你删除最少的数,使得剩下的按位与是1,首先不同数字的按位与如果是1,那么至少有一位全是1,否则如果不存在一位全是1,那么每一位都存在零,每一位都存在零就会导致全部按位与都是0;
另外,cf上的题最好不要按照它给的方式去想,它说删除最少的数,使得至少有一位全是1,其实就是留下最多的数,使得至少有一位全是1,那么我们先预处理每一位是1还是0的情况即可,为了防止超时,对于每一位,设置一个前缀和数组。
# include<iostream>
# include<cstring>
# include<algorithm>
# include<math.h>
# include<cmath>
# include<map>
# include<stack>
# include<iomanip>
# define INF 0x7f7f7f7f7f;
using namespace std;
typedef long long int ll;
typedef unsigned long long int ul;
typedef pair<int,int>pll;
int val[200000+10][40];
void init()
{
for(int i=1;i<=200000;i++)
{
for(int j=0;(1<<j)<=i;j++)
{
if(i&(1<<j)) //数字i二进制第j位是1
val[i][j]++;
}
}
}
void getsum()
{
for(int i=1;i<=200000;i++)
{
for(int j=0;j<=35;j++)
{
val[i][j]+=val[i-1][j]; //前i个数的j位是1的个数和
}
}
}
int main()
{
// 删除最少那就是留下最多,按位与之后只要某一位的1最多,那么留下的就多
init();
getsum();
int t;
cin>>t;
while(t--)
{
int l,r;
scanf("%d%d",&l,&r);
int ans=0;
for(int j=0;j<=35;j++)
{
int temp=val[r][j]-val[l-1][j]; //枚举位数,前缀和求出最大值
ans=max(ans,temp);
}
cout<<r-l+1-ans<<'\n'; //r-l+1是数字个数,减去留下最大的,剩下的就是最小的
}
}