爱丽丝和鲍勃有一个整数 N.爱丽丝和鲍勃对他们的整数不满意。昨天晚上,他们去参加一个鸡尾酒会,发现另一对夫妇的整数完全相同!正因为如此,他们得到了一个新的整数。
Bob想给另一对夫妇留下深刻印象,因此他认为他们的新整数应该严格大于 N。
爱丽丝自己其实也喜欢一些特定的整数 k.因此,Alice认为,无论他们选择哪个整数,都应该可以将其写成 k 个 2 的不同幂。
鲍勃也是个吝啬鬼,所以他想尽量少花钱。由于整数的代价与其大小成正比,他希望得到一个尽可能小的整数。
题意:
给出 N,K,求 M ; M 为大于 N 的可以写成 k 个 2 的几次幂的最小值。
输入
包含两个整数的单行 N 和 k、 其中 1 ≤ N ≤ 1e18和 1 ≤ k ≤ 60。
输出
输出 ?M, M是大于 N 的最小整数,可以写成 k 个 2 的不同幂之和。
Input1
1 2
Output1
3
Input2
12 2
Output2
17
Input3
1 5
Output3
31
Input4
182 3
Output4
193
?
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef pair<int,int> PII;
const double PI=acos(-1.0);
const int N=2e6+10;
int b[63];
void find()
{
b[0]=1;
for (int i=1;i<61;i++) b[i]=b[i-1]*2;
}
int n,k;
bool vis[N];
void solve()
{
find();
cin>>n>>k;
int num=0,cnt=0;
int m=n;
while (n)
{
if (n%2)
{
vis[cnt]=1;
num++;
}
n /=2;
cnt++;
}
int ans=0;
if (k>num) //当 k>num 时,个数不足,从低位开始补1就行
{
ans=m;
k -=num;
for (int i=0;i<61;i++)
{
if (!vis[i])
{
ans +=b[i];
k--;
}
if (k<=0) break;
}
cout<<ans;
return ;
}
if (k<num) //当 k<num 时,从低位开始将1替换成0,让num减小,直到num==k
{
for (int i=0;i<61;i++)
{
if (vis[i]==1)
{
vis[i]=0;
num--;
if (k==num) break;
}
}
}
int j=0; //此时 k==num,从低位找,找到第一个1;
int l=0; //之后继续找,找到第一个0;
while (vis[j]==0&&j<61) j++; //将0之前的1都清空,将这个0变成1,再从低位开始补满k个1
while (vis[j]==1&&j<61)
{
j++;
l++;
}
vis[j]=1;
l--;
for (int i=0;i<j;i++) vis[i]=0;
for (int i=0;i<61;i++)
{
if (vis[i]) ans +=b[i];
else if (!vis[i]&&l>0)
{
ans +=b[i];
l--;
}
}
cout<<ans;
}
signed main()
{
ios;
int T=1;
//cin>>T;
while (T--) solve();
return 0;
}