1. 程式人生 > >Numbers ZOJ

Numbers ZOJ

題意:給出一個數字N以及一個M,要求把N分為M部分且滿足

  • N=a1+a2+a3++amN = a_1 + a_2 + a_3 + \dots+a_m 詢問如何讓a1a2a3ama_1|a_2|a_3|\dots|a_m儘可能的小,輸出最小值。

題解:如果讓後來的或值最小的話,那麼我們首先需要去掉最高位的1(二進位制下),然後我們的工作就成為了從高到低判斷某一位是否放1,我們在判斷某一位的時候我們需要判斷他後面的數字如果全部為1的時候是否比N還要大,如果可以的話,這一位可以不放1,否則的一定要放1,該位放1,那麼相應的其他(m-1)個數字也要放1(讓N儘量的小),然後統計答案即可。(大數不可少

收穫:轉化為一個較為容易實現的問題,如判斷某位是否要放1

accode:ac\ code:

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


public class Main {
	static BigInteger n, m, two = BigInteger.valueOf(2), one = BigInteger.ONE;
	static BigInteger []num = new BigInteger[4000];
	static int top;
	public static void solve() {
		BigInteger ans =
BigInteger.ZERO; for(int i = 0; i < top; i++) { int pos = top - 1 - i; BigInteger dig = two.pow(pos); dig = dig.subtract(one); dig = dig.multiply(m); if(dig.compareTo(BigInteger.ZERO) < 0) { dig = BigInteger.ZERO; } //System.out.println(dig + " " + n); BigInteger ttt =
BigInteger.ZERO; if(dig.compareTo(n) < 0) { ans = ans.add(two.pow(pos)); BigInteger x = two.pow(pos); BigInteger k = n.divide(x); if(k.compareTo(m) > 0) { k = m; } n = n.subtract(k.multiply(x)); } } System.out.println(ans); } public static void main(String [] args) { Scanner cin = new Scanner(System.in); for(int i = 0; i< 3000; i++) num[i] = BigInteger.ZERO; int T = cin.nextInt(); while(T-- > 0) { top = 0; n = cin.nextBigInteger(); m = cin.nextBigInteger(); if(n.equals(BigInteger.ZERO)) { System.out.println("0"); continue; } else if(n.equals(BigInteger.ONE)) { System.out.println("1"); continue; } BigInteger tn = n; while(n.compareTo(BigInteger.ZERO) > 0) { num[top++] = n.mod(BigInteger.valueOf(2)); n = n.divide(BigInteger.valueOf(2)); } for(int i = 0, j = top - 1; i < j; i++, j--) { BigInteger t = num[i]; num[i] = num[j]; num[j] = t; } n = tn; solve(); } } }