zoj3987 Numbers(大数+贪心)

28 篇文章 0 订阅
6 篇文章 0 订阅

Numbers


Time Limit: 2 Seconds      Memory Limit: 65536 KB


DreamGrid has a nonnegative integer . He would like to divide into nonnegative integers and minimizes their bitwise or (i.e. and 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 and ().

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

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

题意:给你一个1e1000的数,让你分成最多1e100位,然后互相进行或运算,得到的值最小

思路:

让高位最小然后向低位贪心,判断当前为能否为0,能为0的条件是,后面几位都是1,并且有m个,加起来如果大于当前值的话 那么这位就可以为0,否则只能为1,既然为1了,那么尽量多填1,这样保证了结果最优

开始没有用pre预处理二进制位,结果超时了。pow在大数中简直不能用。

感受:

反正比赛时我没有推出来。欸。跑偏了。

代码:

pre【i】代表1<<i.

import java.math.BigInteger;
import java.util.Scanner;


public class lalala {
	
	public static void main(String[] args) {
		BigInteger a,b;
		BigInteger tmp,tmp2,tmp3,ans;
		int tol;///代表最多几位
		Scanner sc=new Scanner(System.in);
		int t=sc.nextInt();
		BigInteger pre[]=new BigInteger[7000];
		BigInteger pp=new BigInteger("1");
		for(int i=0;i<=6666;i++){
			pre[i]=pp;
			pp=pp.multiply(new BigInteger("2"));
		}
		while(t!=0){
		t--;
		a=sc.nextBigInteger();
		b=sc.nextBigInteger();
		tmp=a.divide(new BigInteger("2"));
		///tol=tmp.intValue();
		tol=0;
		BigInteger n=a;
        while(n.compareTo(new BigInteger("0"))==1){
            tol++;
            n=n.divide(new BigInteger("2"));
        }
	
		BigInteger sum=new BigInteger("0");
		BigInteger er=new BigInteger("2");
		ans=new BigInteger("0");
		for(;tol>=0;tol--){
			///当前位放0;
			tmp=b.multiply(pre[tol].subtract(new BigInteger("1")));///tmp=b*(pow(2,tol)-1)...就是假设后边所有放1.
			tmp3=a.divide(pre[tol]);///tmp3=a/pow(2,tol);看当前最多能放几个1,能放几个放几个
			if(tmp3.compareTo(b)>0){///如果超过了b个,说明全放
				tmp3=b;
			}
			tmp3=tmp3.multiply(pre[tol]);
			tmp2=sum.add(tmp);///sum+tmp;
			if(tmp2.compareTo(a)<0 ){///说明当前位置必须放1.而且b个数字全放1
				a=a.subtract(tmp3);
				ans=ans.add(pre[tol]);
			}
		}
		System.out.println(ans);
		}
	}

}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值