2017 CCPC 秦皇島 G題
題意
給定非負整數n, m(n < 10^1000, 1<= m < 10^100), 把n分成m個非負整數的和
且使
a1 or a2 or a3 … or am最小
題解
1.對於任意i in [1, m]
a1 or a2 or a3 … or am >= ai
當n % m == 0時, 只要存在i in [1, m] ai < n / m
必存在i in [1, m],ai < n / m此時最優是m個數全是n / m, 答案為n / m
2. 當n % m != 0時,
考慮均攤一部分,在處理剩下一部分.
比如n = 1244, m = 10
n / m = 124, n % m = 4.
從1得, n1 = 1240, m = 10答案是124,那麼這種情況答案至少為125.我們可以考慮把1240先均分,把剩餘的4分均給在其中四個.
然後發現可行答案是125.
通用嗎?
3. 考慮這樣一組樣例, n = 314, m = 10
按照2的方法,先均分310得31, 剩餘4個再均分其中四個,預計答案是32,然而卻不正確.
原因是31(11111)的最低為1, 其中一個在加上1就會產生進位
二進位制為100000,這樣結果就是111111等於63.
所以要考慮剩餘部分均攤產生進位的情況.
- 我們按照貪心來考慮, 假設均攤有進位.
進位之後二進位制最右邊一個1在右起第i個位置, 那麼答案最少包含左邊的二進位貢獻, 所以我們可以考慮把左邊的部分先分給m個數(如果左邊大於0一定夠分,反之參照下面5),因為這個貢獻一定有,然後再考慮分剩下的數
並且前後貢獻互不影響. - 如果左邊是0比如上邊32=100000那麼此時n不能分出m個32就按照32儘可能分配.
這個就是
314 / 10 + 1 = 32
left=314 - 314/32*32 = 26
ans = 32.
然後26 / 10 + 1 = 3
3 = 11B
右起1左邊是 2=10B
left = 26 - 10 * 2 = 6
ans = ans + 2 = 34
left = 6 < 10
ans = ans + 1 = 35
如果left < m且left = 0這個1就不要加了.
java大數搞一搞就可.
import java.util.*;
import java.math.*;
public class Main {
public static void main(String[] args)
{
BigInteger one = BigInteger.ONE;
BigInteger zero = BigInteger.ZERO;
Scanner cin = new Scanner(System.in);
int T = cin.nextInt();
for(int i = 0; i < T; ++i)
{
BigInteger n = cin.nextBigInteger();
BigInteger m = cin.nextBigInteger();
if(n.mod(m).equals(zero)) System.out.println(n.divide(m));
else
{
BigInteger res = zero;
while(n.compareTo(zero) == 1)
{
BigInteger div = n.divide(m).add(one);
BigInteger bit = lowbit(div);
if(bit.equals(div))//左邊為0
{
n = n.subtract(n.divide(div).multiply(div));
res = res.add(div);
}
else
{
div = div.subtract(bit);
n = n.subtract(div.multiply(m));
res = res.add(div);
}
}
System.out.println(res);
}
}
}
public static BigInteger lowbit(BigInteger x)
{
return x.and(x.multiply(new BigInteger("-1")));
}
}