-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
count-k-reducible-numbers-less-than-n.cpp
72 lines (68 loc) · 2.29 KB
/
count-k-reducible-numbers-less-than-n.cpp
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Time: O(n^2)
// Space: O(n)
// dp
vector<int> cnt = {0, 0};
class Solution {
public:
int countKReducibleNumbers(string s, int k) {
static const int MOD = 1e9 + 7;
while (size(s) - 1 >= size(cnt)) { // cached
cnt.emplace_back(cnt[__builtin_popcount(size(cnt))] + 1);
}
vector<int> dp(size(s));
for (int i = 0, curr = 0; i < size(s); ++i) {
for (int j = i - 1; j >= 0; --j) {
dp[j + 1] = (dp[j + 1] + dp[j]) % MOD;
}
if (s[i] != '1') {
continue;
}
dp[curr] = (dp[curr] + 1) % MOD;
++curr;
}
int result = 0;
for (int i = 1; i < size(s); ++i) {
if (cnt[i] < k) {
result = (result + dp[i]) % MOD;
}
}
return result;
}
};
// Time: O(n^2)
// Space: O(n)
// dp, combinatorics
// vector<int> cnt = {0, 0};
class Solution2 {
public:
int countKReducibleNumbers(string s, int k) {
static const int MOD = 1e9 + 7;
vector<int> fact = {1, 1};
vector<int> inv = {1, 1};
vector<int> inv_fact = {1, 1};
const auto& nCr = [&](int n, int k) {
while (size(inv) <= n) { // lazy initialization
fact.emplace_back((static_cast<int64_t>(fact.back()) * size(inv)) % MOD);
inv.emplace_back((static_cast<int64_t>(inv[MOD % size(inv)]) * (MOD - MOD / size(inv))) % MOD); // https://cp-algorithms.com/algebra/module-inverse.html
inv_fact.emplace_back((static_cast<int64_t>(inv_fact.back()) * inv.back()) % MOD);
}
return (((static_cast<int64_t>(fact[n]) * inv_fact[n - k]) % MOD) * inv_fact[k]) % MOD;
};
while (size(s) - 1 >= size(cnt)) { // cached
cnt.emplace_back(cnt[__builtin_popcount(size(cnt))] + 1);
}
int result = 0;
for (int i = 0, curr = 0; i < size(s); ++i) {
if (s[i] != '1') {
continue;
}
for (int c = 0; c <= size(s) - (i + 1); ++c) {
if (cnt[curr + c] < k) {
result = (result + nCr(size(s) - (i + 1), c)) % MOD;
}
}
++curr;
}
return (((result - 1) % MOD) + MOD) % MOD;
}
};