题解:P11968 「ALFR Round 7」T1 二进制与一 II
题意很清楚了不需要大意了。
由于官方题解对于我和我机房的各位伪人来说太过抽象,所以自己写了一篇。
简要思路
显然可以寻找有
我们可以从第
这样有什么意义呢,就是可以找到大于
为
想到这里还要处理比
首先比
文字可能过于抽象,详见代码。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=64;
int T,x,k;
int get(int w,int v){
if(v>w)return 4e18;
if(v==0||w==0)return 0;
int res=1ll<<w-1;v--;
for(int i=1,j=1;i<=v;i++)
res+=j,j*=2;
return res;
}//get操作和上面说的一样
int get1(int w,int v){
if(v>w)return 4e18;
if(v==0||w==0)return 0;
int res=0;
for(int i=1,j=1ll<<w-1;i<=v;i++)
res+=j,j/=2;
return res;
}
signed main(){
cin>>T;
while(T--){
cin>>x>>k;
int now=0,ans=4e18;int k1=k;//now表示当前给高位x补充的大小
for(int i=60;i>=1;i--){
if(!k||i<k)break;
if(((1ll<<i-1)&x)){
k--,now+=1ll<<i-1;
int j=i;
while(((1ll<<j-1)&x)&&j>=k)j--;
ans=min(ans,abs(x-(now+get(j,k))));
//将当前位的1加入now,要找到最小的大于x的,相当于找位数小于i最高位为0的位置找
}
else ans=min(ans,abs(x-(now+get(i,k))));
}
now=0;
k=k1;
for(int i=60;i>=1;i--){
if(!k||i<k)break;
if(((1ll<<i-1)&x))
ans=min(ans,abs(x-(now+get1(i-1,k)))),now+=1ll<<i-1,k--;
//这里找小于x最大值,相当于在x为0的位置的后面尽量多的1在高位
}
cout<<ans<<'\n';
}
return 0;
}