http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3987
题意:
给出一个数n,现在要将它分为m个数,这m个数相加起来必须等于n,并且要使得这m个数的或值最小。
思路:
从二进制的角度分析,如果这m个数中有一个数某一位为1,那么最后或起来这一位肯定是为1的,所以如果某一位为1了,那么我们尽量就让其余位也等于1。
所以我们从最高位开始枚举,看看这一位是否需要为1,如果需要为1的话,那么剩下的几个数也尽量让这一位等于1。
1 import java.math.*; 2 import java.util.Scanner; 3 4 public class Main { 5 public static void main(String[] args) { 6 BigInteger n, m; 7 Scanner in = new Scanner(System.in); 8 int T = in.nextInt(); 9 for(int cas=0;cas<T;cas++){ 10 n = in.nextBigInteger(); 11 m = in.nextBigInteger(); 12 int len = 0; 13 BigInteger ss = n; 14 while(ss.compareTo(BigInteger.ZERO)>0){ 15 ss = ss.divide(BigInteger.valueOf(2)); 16 len++; 17 } 18 BigInteger tmp; 19 BigInteger ans = new BigInteger("0"); 20 for(int i = len; i>0; i--){ 21 if(n.compareTo(BigInteger.ZERO)<=0) break; 22 tmp = BigInteger.valueOf(2).pow(i-1).subtract(BigInteger.valueOf(1)); 23 BigInteger sum = tmp.multiply(m); 24 if(sum.compareTo(n)<0){ 25 BigInteger num = n.divide(BigInteger.valueOf(2).pow(i-1)); 26 if(num.compareTo(m)>0) num = m; 27 n = n.subtract(BigInteger.valueOf(2).pow(i-1).multiply(num)); 28 ans = ans.add(BigInteger.valueOf(2).pow(i-1)); 29 } 30 } 31 System.out.println(ans); 32 } 33 in.close(); 34 } 35 }