ZOJ 3987 Numbers (BigInteger类、贪心)

Numbers


Time Limit: 2 Seconds      Memory Limit: 65536 KB


DreamGrid has a nonnegative integer n. He would like to divide n into m nonnegative integers  and minimizes their bitwise or (i.e.n=a_1 + a_2 + \dots + a_m and a_1 \text{ OR } a_2 \text{ OR } \dots \text{ OR } a_m should be as small as possible).

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains two integers  and  (0 \le n < 10^{1000}, 1 \le m < 10^{100}).

It is guaranteed that the sum of the length of  does not exceed .

Output

For each test case, output an integer denoting the minimum value of their bitwise or.

Sample Input

5
3 1
3 2
3 3
10000 5
1244 10

Sample Output

3
3
1
2000
125

Author: LIN, Xi
Source: The 2017 China Collegiate Programming Contest, Qinhuangdao Site


题意:n由m个数组成,n=a1+a2+...+am。求a1 or a2 or ...or am的最小值。

思路:将n看作由m个二进制数构成的数,对于这m个数,我们希望它们的二进制为1的位置尽可能的低,因为题目要求或运算的结果尽可能的小。

我们从n的二进制最高位开始遍历,这m个数只有当k位置必须放置1时,我们才在第k位放置1,其他情况放置0。必须放置1的情况为:(2^k-1)*m>=n 并且(2*(k-1)-1)*m<n,表示如果我在k位置不放置1,后面的位置全部放置1也小于n,所以我们至少需要在k位置放置1个1,既然这个位置确定要放置1了,我们就尽可能的多放置1,使得后面放置1的位置尽可能的低,ans=ans+2^k。

因为数据的范围很大,需要用到java的BigInteger类

AC代码:

import java.math.BigInteger;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		BigInteger n,m,ans,tmp,num,cnt;
		Scanner sc = new Scanner(System.in);
		int T=sc.nextInt();
		while(T-->0) {
			n = sc.nextBigInteger();
			m = sc.nextBigInteger();
			ans = BigInteger.ZERO;
			tmp = n;
			int len=0;
			while(tmp.compareTo(BigInteger.ZERO)>0) {
				tmp=tmp.divide(BigInteger.valueOf(2));
				len++;
			}
			//组成n的二进制最高位为2^(len-1)
			for(int i=len-1;i>=0;i--) {
				//num1=(2^k-1)*m
				num = BigInteger.valueOf(2).pow(i).subtract(BigInteger.ONE).multiply(m);
				if(num.compareTo(n)<0) {
					cnt = n.divide(BigInteger.valueOf(2).pow(i));
					if(cnt.compareTo(m)>0)
						cnt=m;
					n=n.subtract(BigInteger.valueOf(2).pow(i).multiply(cnt));
					ans=ans.add(BigInteger.valueOf(2).pow(i));
				}
			}
			System.out.println(ans);
		}

	}

}

猜你喜欢

转载自blog.csdn.net/Rainbow_storm/article/details/83041038