简单的异或问题

目录

1.题目

2.解题思路

3.代码思路

4.代码实现

5.附录


1.题目

题目描述

有一组整数 {0,1,2,…,2m -1}, 请从中选出 k 个数,使得这k个数的异或和为n, 请输出最大的满足条件的 k。

输入

第一行一个数t,代表多组样例输入  
每组两个数n和m, 其中 0≤n≤2m-1,1≤m≤60

输出

输出每组最大的满足条件的k。

样例输入

1
2 2

样例输出

3

2.解题思路

        因为题目要求的从0到2^{m}-1里找到最多的k个数,异或后值等于n,因为这k个数进行的是异或运算,也就是这k个数的二进制的每一位上进行的都是异或运算,因为异或运算,同为1异或后为零,仅有1个1异或后为0,也就是说,偶数个1异或后为0,奇数个1异或后为1,经证明知当m不为1时,从0到2^{m}-1的每个数的二进制的各个位上的1相加都为偶数(证明详见附录)。

        因为从0到m-1位的1的总数都为偶数,所以当m!=1时,将这些数都异或后都为0,而题目要求k个数异或后为n,那我们可以根据n的二进制表示的每一位0或者1,由全部数进行异或后为0进行调整,若对应位为0则不变,若为1则可以使对应位1的总数-1。

        经过调整后发现,要调整的01序列,其实就是最后异或得出的n的二进制表示,所以将除去n之外的所有数进行异或就得到了n,则其异或的个数的最大值k=2^{m}-1个.比较特殊的情况是,当n=0时,因为0的二进制表示的每一位都为0,因此将0减去后异或的数与不减去0异或后的数相等,而题目要求的k是最多的异或个数,故当n=0时,k=2^{m}个,当m=1时,则需要另外进行特判。

3.代码思路

        所以,当m!=1且n!=0时,输出2^{m}-1,当m==1且n==1时,输出2,当m==1且n==0时,输出1,其余情况2^{m}

4.代码实现

#include<iostream>

using namespace std;

long long cj(long long m)
{
    long long ans=1;
    for(int i=1;i<=m;i++)   ans=ans<<1;
    return ans;
}

int main()
{
    int t;
    cin >>t;
    while(t--)
    {
        long long n,m;
        cin >>n >>m;
        if(n!=0&&m!=1)  cout <<(cj(m)-1) <<endl;
        else if(n==1&&m==1) cout <<2 <<endl;
        else if(n==0&&m==1) cout <<1 <<endl;
        else cout <<cj(m) <<endl;
    }
    return 0;
}

5.附录 

推导: 当m不为1时,从0到2^{m}-1的每个数的二进制的各个位上的1相加都为偶数

简单列举从0到2^{4}-1

0000

0001

0010

0011

0100

0101

0110

0111

1000

1001

1010

1011

1100

1101

1110

1111

观察发现低位即第1位 ,01交替变化为每隔2^{0}交替1次,交替完1次算一个周期,周期为2^{m}/2^{1},即2^{m-1}

第二位,01交替变化为每隔2^{1}交替1次,周期为2^{m-2}

第三位,01交替变化为每隔2^{2}交替1次,周期为2^{m-3}

第四位,01交替变化为每隔2^{3}交替1次,周期为2^{m-4}

.......

以此类推,第t位的周期个数为2^{m-t}个,而1与0在每个周期中是成对存在的,则每一位的1的个数为周期个数除2,结果为偶数。

推导结束

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值