ZOJ 3987 Numbers (BigInteger類、貪心)
Numbers
Time Limit: 2 Seconds Memory Limit: 65536 KB
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
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
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);
}
}
}