题目
辣个神秘的男人手上有n件装备任你选择,威力分别是从1到n。然鹅可怜的你囊中羞涩,你最多只能带走其中的k件装备。你的目标是使这些装备威力值的异或和(设装备的威力值分别为a1,a2,…ak,则他们的异或和a = a1⊕a2⊕…⊕an)最大。请问最大可以是多少。
输入格式:
装备个数n和以及你最多可以带走装备的个数k(1 <= k <= n <= 10^18)
输出格式:
装备威力值的最大异或和
输入样例1:
4 3
输出样例1:
7
输入样例2:
6 6
输出样例2:
7
代码
#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long int
ll pow(ll a,ll b)
{
ll ans=1;
for(ll i=0;i<b;i++)
ans*=a;
return ans;
}
int main()
{
ll n,k;
cin>>n>>k;
if(k==1)
{
cout<<n<<endl;
return 0;
}
int num=0;
while(n)
{
if(n%2)
n=(n-1)/2;
else
n=n/2;
num++;
}
ll ans=0;
for(int i=0;i<num;i++)
ans+=pow(2,i);
cout<<ans<<endl;
return 0;
}
分析
- 关键在于理解这个异或和是啥意思,就是先把十进制的数化为二进制,然后对应位相同为1相异为0,如3异或2,即11+10=01,结果再转化为十进制,即为1 。
- 第二点就是题目说的是至少取k件也就是说,只要能凑到最大值,取1件也行,比如当k=1时,输出1其实就是n 。
- 当k>1时,会发现n的二进制位一定能再1~n-1中找到一个数的二进制形式与其进行异或和使得n的二进制位为0的变为1,也就是说,n的二进制位有m位数则答案是1+2+…+2的m-1次方