1. 程式人生 > >(二進位制貪心)ZOJ - 3987 Numbers

(二進位制貪心)ZOJ - 3987 Numbers

題意 :將值為 n 的數分解成 m 個數的和,並且使這 m 個數的 or 值最小。

題解 :見程式碼

import java.math.*;
import java.util.*;

public class Main{

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in=new Scanner(System.in);
		BigInteger base[]=new BigInteger[5000];  
		BigInteger two=new BigInteger("2");
		base[0]=BigInteger.ONE;
		for(int i=1;i<5000;i++)
			base[i]=base[i-1].multiply(two);
		
		while(in.hasNext()){
			int t=in.nextInt();
			while(t>0){
				BigInteger n=in.nextBigInteger();
				BigInteger m=in.nextBigInteger();
				BigInteger sum=BigInteger.ZERO;  
				int up=0;                         //  up 二進位制位數的最高位
				for(int i=0;i<5000&&sum.compareTo(n)<0;i++){
					sum=sum.add(m.multiply(base[i]));
					up=i;
				}
				BigInteger nn=n,ans=BigInteger.ZERO;
				for(int i=up;i>=0;i--){
					BigInteger s=base[i].subtract(BigInteger.ONE);  //  假如 第 i 位不取
					if(s.multiply(m).compareTo(nn)>=0) continue;   //  不取第 i 位可以
					// 不取第 i 位不可以
					BigInteger k=nn.divide(base[i]);   
					k=k.min(m);    // 儘可能多的填充
					nn=nn.subtract(k.multiply(base[i]));  
					ans=ans.add(base[i]);   
				}
				System.out.println(ans);
				t--;
			}
		}
	}
}