Numbers ZOJ - 3987(二進制思維+貪心)

Numbers ZOJ - 3987

DreamGrid has a nonnegative integer . He would like to divide into nonnegative integers and minimizes their bitwise or (i.e. and should be as small as possible).
Input

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

The first line contains two integers and ().

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

題意:

將整數nn拆分成mm個數的和,輸出這mm個數的按位或的最小值

分析:

考慮貪心,如果m個數中的某一個數的某一位有一個是1了,那麼最終結果這一位也必定是1,因此我們可以判斷一下分成的這m個數,這個位是否必須要有一個1,那麼如果有,我們就讓儘量多的1在這一位,使得後面的1 儘量少,沒有的話,我們能不放就不放

那麼重點是我們如何去判斷這一位是否至少需要一個1呢?

對於一個數n,首先記錄n的二進制位數,然後我們從高位到低位一位一位的看

對於當前位i,我們看如果分成m個數後,這個位是否必須要有1,如果這一位有1的話說明得有一個2i12^{i-1}(注意從202^0開始的),那麼我們知道第一個比它小的數是2i112^{i-1}-1即這一位後面的位全爲1的情況,我們比較一下如果m個數全都這樣的數,(就是全爲1),這m個數的和如果還比當前n小,說明我們必須至少得要有一個i位爲1,這樣才能湊成n嘛,否則就湊不成了。

這樣如果我們判斷了當前i位必須有一個1(有一個2i12^{i-1}),即(m×(2i11)<nm\times (2^{i-1}-1) < n),此時我們就讓i位上儘可能的多放1,那麼能放多少個呢

當然就是num=n2i1num = \frac{n}{2^{i-1}}了,當然瞭如果num>mnum > m,讓num=mnum = m,然後更新當前n,即n=num×2i1n -= num \times 2^{i-1},答案此時就要加上這個2i12^{i-1},然後剩下的n再次循環判斷

code:

import java.math.BigInteger;
import java.util.Scanner;
public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in = new Scanner(System.in) ;
        BigInteger n,m;
        int T = in.nextInt();
        while((T--) > 0) {
        	n = in.nextBigInteger();
        	m = in.nextBigInteger();
        	int len = 0;
        	BigInteger tmp = n;
        	while(tmp.compareTo(BigInteger.ZERO) > 0) {
        		tmp = tmp.shiftRight(1);
        		len++;
        	}
        	BigInteger ans = BigInteger.ZERO;
        	for(int i = len; i > 0; i--) {
        		if(n.compareTo(BigInteger.ZERO) <= 0) break;
        		tmp = BigInteger.valueOf(2).pow(i-1).subtract(BigInteger.ONE);
        		BigInteger sum = tmp.multiply(m);
        		if(sum.compareTo(n) < 0) {
        			BigInteger num = n.divide(BigInteger.valueOf(2).pow(i-1));
        			if(num.compareTo(m) > 0) num = m;
        			n = n.subtract(BigInteger.valueOf(2).pow(i-1).multiply(num));
        			ans = ans.add(BigInteger.valueOf(2).pow(i-1));
        		}
        	}
        	System.out.println(ans);
        	
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章