题目
输入正整数N,求从1到N所有数包含的二进制1的个数。
题解
这是一道找规律题==。
例:对于nums=1101(2进制)的方法compute(nums):
- 可以把它分成[1000(二进制),1101(2进制)]中二进制1的个数、[000(二进制),111(二进制)]中二进制1的个数两部分求解,再将两部分相加。
- 第二部分可以看做是m位二进制可表示的所有数所包含的二进制1的个数,找规律可得,
ansPart2=Math.pow(2,bitPosLen-1)*bitPosLen
- 第一部分则可以递归计算:
ansPart1=[1000(二进制),1101(2进制)]范围内二进制最高位包含的二进制1个数+compute(101(二进制))。
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t=in.nextInt();
while(t--!=0){
int num=in.nextInt();
long ans=bitOneCntContains(num);
System.out.println(ans);
}
}
private static long bitOneCntContains(int nums){
if(nums<=1){
return nums==1?1:0;
}
// 寻找二进制最高位
int bitPos=0;
for(bitPos=0;bitPos<100;++bitPos){
if(Math.pow(2,bitPos)>nums){
break;
}
}
int bitHeighestPos=bitPos-1;// nums二进制最高位
// 计算ansPart1(例如:对于nums=1101(2进制),ansPart1=[1000(二进制),1101(2进制)]中二进制1的数量)
int minNum=(int)Math.pow(2,bitHeighestPos);// 对应二进制最高位为1,其他位为0的数字
int cnt=nums-minNum+1;// 从0到nums,最高位包含1的数量
long ansPart1=bitOneCntContains(nums-minNum)+cnt;
// 计算ansPart2(例如:对于nums=1101(2进制),ansPart2=[000(二进制),111(二进制)]中二进制1的数量)
int bitPosLen=bitHeighestPos;// 除了最高位二进制的位数
long ansPart2=(long)Math.pow(2,bitPosLen-1)*bitPosLen;// 找规律可得
return ansPart1+ansPart2;
}
}