ZOJ 3987 秦皇岛现场赛G题 java

来源:互联网 发布:雷风影视cms破解版 编辑:程序博客网 时间:2024/05/06 02:03

题目连接:ZOJ 3987

原网页含有mathtype公式,复制过来会乱,所以这里就不放题了。

题意:给2个大数n和m,要求把n分成m个数相加,并且取或运算后最小。

题目分析:

首先考虑将n平分m份,如果恰好可以平分即n%m==0,则答案就是n/m。

之后考虑无法平分的情况,n/m+1会产生二进制的进位,如n=15,m=4的情况,n/m=3,n/m+1=4,产生了进位。考虑n/m+1用二进制表示,取其lowbit,比如n=32,m=6,

则n/m+1=6=110,其lowbit就是把最右边的1变为0,lowbit(6)=4;此时这m个数是一定会加上4的,剩下的再重复上述步骤,知道剩下的数小于m。如果n/m+1是2的次方数,lowbit数不变,此时这个数也是一定要取的,不过只能尽量多的取,如上述n=15,m=4的情况,前三个每个取4,后一个不取。

最后考虑n=32,m=6的情况:第一步n/m+1=6,取4,剩余32-6*4=8,8/6+1=2,则前3个数+2,后面3个数不变,剩下0,结束。

lowbit就是x&(-x)。

由于这里需要大数取模,相减,以及与运算,所以在没有详尽的大数模板情况下java是个不错的选择。

import java.io.*;import java.util.*;import java.math.*;public class Main {public static void main(String[] args){int T;BigInteger m,n,div,left,l;BigInteger []t=new BigInteger[1111];Scanner cin=new Scanner(System.in);T=cin.nextInt();for(int kase=0;kase<T;kase++){n=cin.nextBigInteger();m=cin.nextBigInteger();div=n.divide(m);if(n.equals(m.multiply(div))){System.out.println(div);continue;}BigInteger ans=BigInteger.valueOf(0);left=n;div=div.add(BigInteger.valueOf(1));while(left.compareTo(BigInteger.ZERO)==1){BigInteger bit=lowbit(div);if(bit.equals(div)){ans=ans.add(div);BigInteger buf=left.divide(div);buf=buf.multiply(div);left=left.subtract(buf);div=left.divide(m);div=div.add(BigInteger.valueOf(1));}else{BigInteger buf=div.subtract(bit);ans=ans.add(buf);buf=buf.multiply(m);left=left.subtract(buf);div=left.divide(m);div=div.add(BigInteger.valueOf(1));}}System.out.println(ans);}}private static BigInteger lowbit(BigInteger div) {return div.and(div.multiply(BigInteger.valueOf(-1)));}}


阅读全文
0 0
原创粉丝点击