Live Archive 6527 Counting ones

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

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;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值