题目描述 给你两个正整数n和m,你需要把n分裂成m个数相加的形式n=a1+a2+a3+.....+am,使a1 or a2 or a3 or.......or am的值最小,其中or位或运算 输入 第一行一个正整数T(1<=T<=100) 接下来的2~T+1行,每行两个正整数n和m(0<=n<1e19,1<=m<=1e19) 输出 对于每组n和m,输出一个整数,表示其按位 or 的最小值。 样例输入 5 3 1 3 2 3 3 10000 5 1244 10 样例输出 3 3 1 2000 125
时间: 2023-05-29 08:01:10 浏览: 171
解题思路
看到位运算,自然想到将n的每一位分别拆分成二进制,将m个数从高位向低位填,使得或后结果最小。有点类似于贪心的思想,每次尝试填1,如果不行再填0。
具体来说,首先将n和m转化为二进制形式的字符串,如果n的二进制位数小于m,则将n左边补0,以便于后面的处理。接着,从高位向低位遍历n的每一位(从左往右),如果该位为1,则将该位所表示的二进制数(即 $2^i$)分给第一个数,否则分给第二个数,并更新其二进制表示方式。然后,再向第三个数、第四个数填数,直到第m个数填完。最后,将所有数按位或即为最小值。
需要注意的细节:
- 因为高位对结果的影响更大,所以 从高位向低位 填数可以使得结果更小。
- 由于n的二进制长度可能小于m,进行位运算操作前需要将n的二进制字符串长度设为m,左边补0。
- 如果n的二进制长度大于m,则前m个二进制位必须每个都是1,否则位或后结果不是最小的。
- 如果m比n二进制长度大,由于数字分配之后最小值只和最高位上的数字有关,所以第一个数得到的数字既可以和最高位上的数一样,也可以是1或0。不过,如果第一个数分得太少,后面的数比较难填,增加了问题的难度。
参考代码
阅读全文