一道关于位运算的O(1)解法(位运算、集合论、均值不等式)

发布时间 2023-11-20 22:56:26作者: hlllz

题目:
给你三个整数 a ,b 和 n ,请你返回 (a XOR x) * (b XOR x) 的 最大值 且 x 需要满足 0 <= x < 2n。

由于答案可能会很大,返回它对 109 + 7 取余 后的结果。

注意,XOR 是按位异或操作。
题解:
XOR的定义:对于两个二进制位,如果相同则结果为0,不同则结果为1。
先不看n只看a和b,ax和bx越大肯定越好,当a和b一个位相同时,x只要取反就能取得a和b该位上的1,当一个位不相同时(其中一个为0,另外一个为1),这里需要考虑分配给a还是b。首选能想到的时这个1不论分配给谁,ax+bx = 定值,根据均值定理,a与b越接近,乘积也就越大。这里需要考虑怎么分配1,减少ax和bx的差距。
现在我们假设a>b,分情况讨论:
情况1:a和b的高位都相等,把最高位的1分配给其中一个,其他的只能分配给另外一个
情况2:a和b的高位不相等,无论怎么分配,a永远比b要大,所以需要把所有1分配给b

常用运算技巧:
集合运算:
image
集合与元素:
image
函数库:
image
最后代码:

点击查看代码
        public int maximumXorProduct(long a, long b, int n) {
            int mod = (int) (Math.pow(10, 9) + 7);
            if (a < b) {
                long tmp = a;
                a = b;
                b = tmp;
            }
            long mask = (1L << n) - 1;
            //取不变的高位
            long ax = a & ~mask;
            long bx = b & ~mask;
            //保留低位
            a &= mask;
            b &= mask;

            //不同的部分
            long diff = a ^ b;
            //相同的部分
            long same = diff ^ mask;

            //加入相同的部分
            ax |= same;
            bx |= same;

            //有不同的部分需要分配
            if (diff > 0 && ax == bx) {
                //高位给a
                long highBit = 1L << (64 - Long.numberOfLeadingZeros(diff) - 1);
                ax |= highBit;
                //从diff中移除
                diff ^= highBit;
            }
            //剩下的给b
            bx |= diff;


            ax %= mod;
            bx %= mod;
            return Math.toIntExact((ax * bx) % mod);
        }