题目大意
将一个数n拆分为m个数之和,求这m个数进行或操作后的最小值
题解
考虑贪心,我们知道,m个数的二进制中某一位有一个为 1 ,最终的结果这一位一定是 1,因此尽可能多的让这 m 个数充满二进制的这一位则为最优 记录 n 的二进制位数,从高位向低位开始枚举,对于当前位 i ,首先判断 n 是否可以充满 m 个 i 位以下的部分 若可以,则说明溢出部分会被放置在当前位,于是尽可能多的填充当前第 i 位共 m 个二进制位 若不可以,则说明剩余的数字可以被安置在低位,当前位为 0import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static BigInteger n,m;
public static void solve() {
int len=0;
BigInteger tmp=n;
len=tmp.bitLength();
BigInteger ans=BigInteger.valueOf(0);
for(int i=len-1;i>=0&&n.compareTo(BigInteger.valueOf(0))>0;i--) {
BigInteger cnt=BigInteger.ONE.shiftLeft(i);
tmp=cnt.subtract(BigInteger.valueOf(1)).multiply(m);// 检验n是否可以填满m个低位
if(tmp.compareTo(n)<0) { // 若不可以填满则说明当前位一定被占用
n=n.subtract(cnt.multiply(m.min(n.shiftRight(i))));// 尽可能多的填充当前位
ans=ans.or(cnt);
}
}
System.out.println(ans);
}
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
int t;
t=cin.nextInt();
while(t-->0) {
n=cin.nextBigInteger();
m=cin.nextBigInteger();
solve();
}
}
}
学如逆水行舟,不进则退