Live Archive 6527 Counting ones
题目大意:给出满足(1 ≤ A ≤ B ≤ 10^16 )的两数A、B,统计从A到B(闭区间)的所有数中共有多少位是'1'。
题目分析:先来看从0开始的一组数据
0000000
0000001
0000010
0000011
0000100
0000101
0000110
0000111
0001000不难发现从最低位(设为第1位)开始,所有位都符合这样的规律,第i位每2^i个数一个轮回,先出现2^(i-1)次0,再出现2^(i-1)次1。
然后就可以把问题拆开了,分别统计A、B每一位上的'1'的个数,每一位上B的个数加起来就是答案
code:
import java.math.BigInteger;
import java.util.BitSet;
import java.util.Scanner;
public class Main {
static BitSet bss,bse;
static BigInteger bi1,bi2,count;
static BigInteger one=BigInteger.ONE,two=new BigInteger("2"),zero=BigInteger.ZERO;
public static void main(String[] args) {
String st;
Scanner in=new Scanner(System.in);
while(in.hasNext()){
st=new String(in.nextLine());
bi1=new BigInteger(st.substring(0,st.indexOf(" ")));
bi2=new BigInteger(st.substring(st.indexOf(" ")+1,st.length()));
System.out.println("bi1=="+bi1);
System.out.println("bi2=="+bi2);
bi2=bi2.add(one);
int i=0;/*
bss=new BitSet(100);
while(!bi1.equals(zero)){
if(bi1.mod(two).equals(one))bss.set(i);
bi1=bi1.divide(two);
i++;
}
i=0;
bse=new BitSet(100);
while(!bi2.equals(zero)){
if(bi2.mod(two).equals(one))bse.set(i);
bi2=bi2.divide(two);
i++;
}
System.out.println("bss=="+bss);
System.out.println("bse=="+bse);*/
count=zero;
BigInteger s,x,k=two,temp1,temp2;
for(i=0;i<100;i++,k=k.multiply(two)){
temp1=bi1.mod(k).compareTo(k.divide(two))<0?zero:bi1.mod(k).subtract(k.divide(two));
temp2=bi2.mod(k).compareTo(k.divide(two))<0?zero:bi2.mod(k).subtract(k.divide(two));
s=bi1.divide(k).multiply(k).divide(two).add(temp1);
x=bi2.divide(k).multiply(k).divide(two).add(temp2);
count=count.add(x.subtract(s));
}
System.out.println(count);
}
}
private static BitSet add(BitSet bs){
int i=0;
while(bs.get(i)){
bs.clear(i);
i++;
}
bs.set(i);
return bs;
}
}

本文解析了LiveArchive 6527 Counting Ones的问题,通过观察二进制数规律,设计算法统计指定范围内数字中'1'的总数。使用Java实现并提供了完整的代码示例。
9507

被折叠的 条评论
为什么被折叠?



