您的位置:首页 > 其它

2017 CCPC 秦皇岛 G题

2017-10-30 18:22 441 查看

题意

给定非负整数n, m(n < 10^1000, 1<= m < 10^100), 把n分成m个非负整数的和

∑i=1mai=n(ai>=0)

且使

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")));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ccpc