QUESTION
easy
题目描述
给定两个整数 L
和 R
,找到闭区间 [L, R]
范围内,计算置位位数为质数的整数个数。
(注意,计算置位代表二进制表示中1的个数。例如 21
的二进制表示 10101
有 3
个计算置位。还有,1 不是质数。)
示例 1:
输入: L = 6, R = 10
输出: 4
解释:
6 -> 110 (2 个计算置位,2 是质数)
7 -> 111 (3 个计算置位,3 是质数)
9 -> 1001 (2 个计算置位,2 是质数)
10-> 1010 (2 个计算置位,2 是质数)
示例 2:
输入: L = 10, R = 15
输出: 5
解释:
10 -> 1010 (2 个计算置位, 2 是质数)
11 -> 1011 (3 个计算置位, 3 是质数)
12 -> 1100 (2 个计算置位, 2 是质数)
13 -> 1101 (3 个计算置位, 3 是质数)
14 -> 1110 (3 个计算置位, 3 是质数)
15 -> 1111 (4 个计算置位, 4 不是质数)
说明
- L, R 是 L <= R 且在
[1, 10^6]
中的整数。 - R - L 的最大值为
10000
。
SOLUTION
首先 L
和 R
是在 [1, 10^6]
范围内的整数,那么二进制可以用 20 位来表示这个数(2^20 = 1,048,576),所以质数的可能存在的范围是 [0, 20]
。
此范围内的质数有 [2, 3, 5, 7, 11, 13, 17, 19]
方法一
用 bitset<21>
作为一张质数表,另外通过按位与来统计 1 的个数
class Solution {
public:
int countPrimeSetBits(int L, int R) {
int res = 0;
bitset<21> bs(string("10100010100010101100"));
for(int i = L; i <= R; i++){
int cnt = 0, tmp = i;
while(tmp > 0) {
if(tmp & 1) cnt++;
tmp >>= 1;
}
if(bs[cnt]) res++;
}
return res;
}
};
方法二
实际上 bitset
自带一个统计的方法,见下
class Solution {
public:
int countPrimeSetBits(int L, int R) {
int res = 0;
bitset<21> bs(string("10100010100010101100"));
for(int i = L; i <= R; i++){
bitset<32> b(i);
if(bs[b.count()]) res++;
}
return res;
}
};
方法三
看过来一个方法用了 __builtin_popcount()
用于计算一个 32 位无符号整数有多少个位为 1,我好像有点晕
class Solution {
public:
int countPrimeSetBits(int L, int R) {
int res = 0;
bitset<21> bs(string("10100010100010101100"));
for(int i = L; i <= R; i++){
int cnt = __builtin_popcount(i);
if(bs[cnt]) res++;
}
return res;
}
};