2017 CCPC 秦皇岛 G题

题意

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

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

且使 
a 1  or a 2  or a 3  … or a m 最小

题解

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. 我们按照贪心来考虑, 假设均摊有进位. 
    进位之后二进制最右边一个1在右起第i个位置, 那么答案最少包含左边的二进位贡献, 所以我们可以考虑把左边的部分先分给m个数(如果左边大于0一定够分,反之参照下面5),因为这个贡献一定有,然后再考虑分剩下的数 
    并且前后贡献互不影响.
  2. 如果左边是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")));
    }
}

原文:http://blog.csdn.net/adjky/article/details/78395776

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值