2017CCPC秦皇岛G ZOJ 3987Numbers(大数+贪心)

Time Limit: 2 Seconds       Memory Limit: 65536 KB

DreamGrid has a nonnegative integer n . He would like to divide n into m nonnegative integers a1,a2,...am and minimizes their bitwise or (i.e.a1+a2+...+am=n  and a1 OR a2 OR a3...OR am should be as small as possible).

Input

There are multiple test cases. The first line of input contains an integer , indicating the number of test cases. For each test case:

The first line contains two integers n and  m( 0<=n<=1e1000 1<=m<=1e100).

It is guaranteed that the sum of the length of does not exceed 20000

Output

For each test case, output an integer denoting the minimum value of their bitwise or.

Sample Input
5
3 1
3 2
3 3
10000 5
1244 10
Sample Output
3
3
1
2000
125

Author: LIN, Xi
Source: The 2017 China Collegiate Programming Contest, Qinhuangdao Site

/*
* 题意:给你一个1e1000的数,让你分成最多1e100位,然后互相进行或运算,得到的值最小
*
* 思路:让高位最小然后向低位贪心,判断当前为能否为0,能为0的条件是,后面几位都是1,并且有m个,加起来如果大于当前值的话
*   那么这位就可以为0,否则只能为1,既然为1了,那么尽量多填1,这样保证了结果最优    
* */
import java.math.BigInteger;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        // write your code here
        Scanner in=new Scanner(System.in);
        int t;
        BigInteger n,m,x,sum;
        BigInteger [] pre=new BigInteger[4005];//表示后缀和
        String s;
        x=new BigInteger("1");
        pre[0]=new BigInteger("0");
        for(int i=1;i<4005;i++){
            pre[i]=pre[i-1].add(x);
            x=x.multiply(new BigInteger("2"));
        }
        t=in.nextInt();
        for(int ca=0;ca<t;ca++){
            n=in.nextBigInteger();
            m=in.nextBigInteger();
            sum=n;
            int tol=0;
            while(n.compareTo(new BigInteger("0"))==1){
                tol++;
                n=n.divide(new BigInteger("2"));
            }
            x=new BigInteger("0");
            //判断这一位的累加和能不能用后边的所有空间放下,能的话就转移到下一位,不能的话就把这一位都填满
            for(int i=tol;i>=1;i--){//枚举每位
                x=x.multiply(new BigInteger("2"));
                int ok=sum.compareTo(pre[i - 1].multiply(m));
                if ( ok<=0) {//能用剩余的空间放下
                    continue;
                } else {//放不下
                    x = x.add(new BigInteger("1"));
                    BigInteger cur = pre[i].subtract(pre[i - 1]);
                    BigInteger cnt = sum.divide(cur);
                    if (cnt.compareTo(m) >= 0) {
                        sum = sum.subtract(cur.multiply(m));
                    } else {
                        sum = sum.subtract(cur.multiply(cnt));
                    }
                }
            }
            System.out.println(x);
        }
    }
}


//package aax;

import java.math.BigInteger;

import java.util.Scanner;

public class Main{
	public static void main(String[] args){
		Scanner in=new Scanner(System.in);
		int t;
		BigInteger n, m, x, sum;
		BigInteger []pre=new BigInteger[4005];
		String s;
		x=new BigInteger("1");
		pre[0]=new BigInteger("0");
		for(int i=1;i<4005;i++)
		{
			pre[i]=pre[i-1].add(x);
			x=x.multiply(new BigInteger("2"));
		}
		t=in.nextInt();
		for(int cas=0;cas<t;cas++)
		{
			n=in.nextBigInteger();
			m=in.nextBigInteger();
			sum=n;
			int tol=0;
			while(n.compareTo(new BigInteger("0"))==1)
			{
				tol++;
				n=n.divide(new BigInteger("2"));
			}
			x=new BigInteger("0");
			for(int i=tol;i>=1;i--)
			{
				x=x.multiply(new BigInteger("2"));
				int ok=sum.compareTo(pre[i-1].multiply(m));
				if(ok<=0)
				{
					continue;
				}
				else
				{
					x=x.add(new BigInteger("1"));
					BigInteger cur=pre[i].subtract(pre[i-1]);
					BigInteger cnt=sum.divide(cur);
					if(cnt.compareTo(m)>=0)
					{
						sum=sum.subtract(cur.multiply(m));
					}
					else
					{
						sum=sum.subtract(cur.multiply(cnt));
					}
				}
			}
			System.out.println(x);
		}
	}
}











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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值