G - Numbers ZOJ - 3987 (大数+贪心)

题目链接走~~~~~

这次不能甩锅了呜呜呜。

先讲一下题意,就是给你一个数分成m组,使他们的或最小。

分析:

一开始想太简单了,有点先入为主的意思,虽然想到了,均分二进制位会使或值最小,但是当无法恰好均分时,无法处理了

。。。自闭

接下来是重点了呢:

我们可以不断的按位来分,

首先,我们要找到他的最高位,如果(2 * k - 1 ) * m > n > (2 *(k-1) - 1) * m, 然后我们就必须把k位赋为1, 为什么呢? 你可以想一下 (2 * k - 1 ) * m 了, 然后如果 再不分的话,就会超过m份。

然后我们就看它最多可以分为多少份, 不断地减去,直到分完为止。

首先是java大数代码,存个板子:

import java.math.BigInteger;
import java.util.Scanner;
 
public class Main 
{
	public static BigInteger two = BigInteger.valueOf(2);
	public static BigInteger one = BigInteger.ONE;
	public static BigInteger zero = BigInteger.ZERO;
	public static BigInteger n, m;
	public static BigInteger a[] = new BigInteger[4005];
	public static void init()
	{
		a[0] = one;
		for(int i = 1; i <= 4002; i++)
			a[i] = a[i - 1].multiply(two);
	}
	public static void main(String[] args) 
	{
		Scanner cin = new Scanner(System.in);
		int t = cin.nextInt();
		init();
		while(t > 0)
		{
			t--;
			int up = 0;
			n = cin.nextBigInteger();
			m = cin.nextBigInteger();
			BigInteger sum = zero, temp = n, ans = zero;
			for(int i = 0; sum.compareTo(n) < 0; i++)
			{
				sum = sum.add(m.multiply(a[i]));
				up = i;
			}
			for(int i = up; i >= 0; i--)
			{
				BigInteger b = a[i].subtract(one);
				//if(T.multiply(m).compareTo(temp) >= 0) continue;
				if((b.multiply(m)).compareTo(temp) >= 0) continue;
				BigInteger k = temp.divide(a[i]); // 可以分为几个
				k = k.min(m);
				ans = ans.add(a[i]);
				temp = temp.subtract(a[i].multiply(k)); // 减去
			}
			System.out.println(ans);
		}
		cin.close();
	}
}

python 代码:难受的是python2.x快被我忘干净了,3.x语法orz

t = int(input())
while t > 0:
    t -= 1
    a, b = map(int, raw_input().split())
    num = 1
    ans = 0
    while (num - 1) * b <= a:
        num *= 2
    while a > 0:
        while (num - 1) * b >= a:
            num /= 2
        ans += num
        if num * b < a:
            a -= num * b
        else:
            a = a % num
    print ans

猜你喜欢

转载自blog.csdn.net/fighting_yifeng/article/details/89228420