数的度量
https://www.acwing.com/problem/content/1083/
思路
这个题相当于把一个数字转化为\(b\)进制, 然后去看小于等于它的数中有多少个在\(b\)进制下, 有\(k\)个\(1\)且其他位全部为0.
\(对于每一位x, 左边的分支为该位取0到x-1,首先该位可取0,然后有两种情况\)
- 若x>1, 该位为0情况已算, 直接算该位为1的情况, 并且直接break.
- 若x==1,同样该位为0情况已算, 那么该位只能取1并且接着看下一位.
\(右边的分支为取x\)
代码
#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define pb push_back
#define PII pair<int, int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
const int N = 35;
int k, b;
int C[N][N];
void init() {
for (int i = 0; i < N; ++i)
for (int j = 0; j <= i; ++j)
if (!j) C[i][j] = 1;
else C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
int f(int n) {
if (!n) return 0;
vector<int> num;
while (n) num.pb(n % b), n /= b;
n = num.size();
int res = 0, last = 0;
for (int i = n - 1; i >= 0; --i) {
int x = num[i];
if (x) { //枚举选0 ~ x - 1的情况
res += C[i][k - last]; //该位选0
if (x > 1) {
if(k - last - 1 >= 0) res += C[i][k - last - 1]; //该位选1, 后面选出k - last - 1个1
break;
}
else {
++last;
if (last > k) break;
}
}
if (!i && k == last) ++res; //最右侧的分支
}
return res;
}
int main() {
IO;
init();
int l, r;
cin >> l >> r >> k >> b;
cout << f(r) - f(l - 1) << '\n';
return 0;
}