Numbers ZOJ - 3987[思維暴力]
阿新 • • 發佈:2018-11-07
題意:給出一個數字N以及一個M,要求把N分為M部分且滿足
-
詢問如何讓 儘可能的小,輸出最小值。
題解:如果讓後來的或值最小的話,那麼我們首先需要去掉最高位的1(二進位制下),然後我們的工作就成為了從高到低判斷某一位是否放1,我們在判斷某一位的時候我們需要判斷他後面的數字如果全部為1的時候是否比N還要大,如果可以的話,這一位可以不放1,否則的一定要放1,該位放1,那麼相應的其他(m-1)個數字也要放1(讓N儘量的小),然後統計答案即可。(大數不可少
收穫:轉化為一個較為容易實現的問題,如判斷某位是否要放1
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();
}
}
}