1. 程式人生 > >ZOJ 3987 Numbers (BigInteger類、貪心)

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, XiSource: 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);
		}

	}

}