2017 CCPC 秦皇岛 G 题 & ZOJ 3987 - Numbers (高精度+贪心)


题目大意

将一个数n拆分为m个数之和,求这m个数进行或操作后的最小值

题解

考虑贪心,我们知道,m个数的二进制中某一位有一个为 1 ,最终的结果这一位一定是 1,因此尽可能多的让这 m 个数充满二进制的这一位则为最优 记录 n 的二进制位数,从高位向低位开始枚举,对于当前位 i ,首先判断 n 是否可以充满 m 个 i 位以下的部分 若可以,则说明溢出部分会被放置在当前位,于是尽可能多的填充当前第 i 位共 m 个二进制位 若不可以,则说明剩余的数字可以被安置在低位,当前位为 0
import java.math.BigInteger;
import java.util.Scanner;

public class Main {
	static BigInteger n,m;
	
	public static void solve() {
		int len=0;
		BigInteger tmp=n;
		len=tmp.bitLength();
		BigInteger ans=BigInteger.valueOf(0);
		for(int i=len-1;i>=0&&n.compareTo(BigInteger.valueOf(0))>0;i--) {
			BigInteger cnt=BigInteger.ONE.shiftLeft(i);
			tmp=cnt.subtract(BigInteger.valueOf(1)).multiply(m);// 检验n是否可以填满m个低位
			if(tmp.compareTo(n)<0) { // 若不可以填满则说明当前位一定被占用
				n=n.subtract(cnt.multiply(m.min(n.shiftRight(i))));// 尽可能多的填充当前位
				ans=ans.or(cnt);
			}
		}
		System.out.println(ans);
	}
	
	public static void main(String[] args) {
		Scanner cin=new Scanner(System.in);
		int t;
		t=cin.nextInt();
		while(t-->0) {
			n=cin.nextBigInteger();
			m=cin.nextBigInteger();
			solve();
		}
	}
}
学如逆水行舟,不进则退
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一百个Chocolate

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值