ZOJ3987(二进制枚举+java大数)
来源:互联网 发布:人工智能招聘信息 编辑:程序博客网 时间:2024/05/18 16:36
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3987
题意:给一个数n和一个数m,让你将n这个数分成m个数相加,且这m个数的or值最小。
思路:直接从二进制角度考虑,要使得m个数的or值最小,也就是说m个数中最高位应该尽量低,我们先假设存在一个k使得
(2^k-1)*m > n > (2^(k-1)-1)*m,那么可以知道m个二进制数中至少有一个数的最高位为k。因为现在我们做或运算,所以此时应让尽量多的数的第k位为1,那么答案ans += 2^k,从高位向低位递推,直到n变为0即可。
代码:
import java.util.*;import java.math.*;public class Main{ public static void main(String[] args){ Scanner cin=new Scanner(System.in); int T=cin.nextInt(); while(T-->0){ BigInteger n=cin.nextBigInteger(); BigInteger m=cin.nextBigInteger(); BigInteger ans=BigInteger.valueOf(0); BigInteger nn=n; int len=0; while(nn.compareTo(BigInteger.ZERO)>0){ nn=nn.divide(BigInteger.valueOf(2)); len++; } for(int i=len-1;i>=0;i--){ BigInteger num1=BigInteger.valueOf(2).pow(i).subtract(BigInteger.ONE); BigInteger num2=num1.multiply(m); while(num2.compareTo(n)<0){ BigInteger num3=n.divide(BigInteger.valueOf(2).pow(i)); if(num3.compareTo(m)>0) num3=m; n=n.subtract(BigInteger.valueOf(2).pow(i).multiply(num3)); ans=ans.add(BigInteger.valueOf(2).pow(i)); } } System.out.println(ans); } }}
阅读全文
0 0
- ZOJ3987(二进制枚举+java大数)
- zoj3987—Numbers(贪心)
- HDU Divided Land(Java大数,二进制大数最大公约数)
- 大数相加(二进制)
- hdu5050(Java大数 + 二进制 + 最大公约数)
- hdu1796(二进制枚举)
- HDU 5050 Java 大数类+读入二进制
- hdu 3118(二进制枚举)
- POJ 3279 (枚举+二进制)
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- 二进制枚举
- hdu5050.Divided Land (二进制求GCD)(Java大数随便搞)
- 1017. A除以B (20)——C语言
- 比较合适的专栏文章
- kruskal算法的实现
- Android在onCreat方法例运行帧动画卡在第一帧的简洁解决方法
- 一年招聘会,一度有发现
- ZOJ3987(二进制枚举+java大数)
- Visual Studio 2017 调试若干问题
- 第一篇
- 转载——探寻C++最快的读取文件的方案std::ios::sync_with_stdio(false)——转载
- 集合的运算
- 1020
- 赶路人。
- 如何在laravel5.5中连接并使用多个数据库
- iOS开发—对NSOperation操作设置依赖关系