0%

600. 不含连续1的非负整数

600.不含连续1的非负整数

题目描述:

给定一个正整数 n ,请你统计在 [0, n] 范围的非负整数中,有多少个整数的二进制表示中不存在 连续的 1

数据范围:

$1\le n \le 10^9$

题解:

数位dp,注意等于 $len$ 时需要返回 $!isLead$,也就是不全部是 $0$。但是这个题目用不到 $isLead$,因为前导零不影响连续的 $1$,因此可以不考虑,那么就直接返回 $1$。

另外就是需要将数转换为二进制,而且需要翻转一下。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
auto optimize_cpp_stdio = []()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout.tie(nullptr);
return 0;
}();
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const int INF = 0x3f3f3f3f;
string s;
int len;
int dp[30][2]; // 当前step,当前位状态,是否是 1
int dfs(int step, int pre, bool isLimit)
{
if (step == len)
return 1;
if (!isLimit && dp[step][pre] != -1)
return dp[step][pre];
int ans = 0;
int up = isLimit ? s[step] - '0' : 1;
for (int i = 0; i <= up; ++i)
{
if (i == 1 && pre == 1)
continue;
ans += dfs(step + 1, i, isLimit && i == up);
}
if (!isLimit)
dp[step][pre] = ans;
return ans;
}
int findIntegers(int n)
{
while (n)
{
if (n & 1)
s.push_back('1');
else
s.push_back('0');
n >>= 1;
}
reverse(s.begin(), s.end());
len = s.length();
memset(dp, -1, sizeof(dp));
return dfs(0, -1, true);
}
};