题目
分析
数位DP可以解决“区间内满足某种性质的数的个数”的问题
通常按照数位分支,形成一颗数位树
最左分支的值由上界值决定,右分支可以直接计算权重
有可能最左分支会有一个权重
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 34;
int c[N][N];
int a[N];
int x, y, k, b;
void init(int n)
{
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 dp(int n)
{
if(!n) return 0;
int res = 0, cnt = 0;
while(n) {a[++cnt] = n % b, n /= b;}
int t = 0;
for(int i = cnt; i; i--)
{
if(a[i]) //a[i] != 0 才会产生答案
{
res += c[i-1][k-t]; //为0的右分支权重
if(a[i] > 1) //如果限定值>1,存在为1的右分支
{
if(k-t-1 >= 0) res += c[i-1][k-t-1]; //注意检查采取该分支剩下的枚举个数是否合法
break; //左分支>2,不用继续搜索
}
else
{
t++; //如果限定值=1,那么此时被迫必须在当前位取1
if(t > k) break;
}
}
if(i == 1 && t == k) res++; //最左分支如果合法,也取
}
return res;
}
int main()
{
init(N-1);
scanf("%d%d%d%d", &x, &y, &k, &b);
printf("%d", dp(y) - dp(x-1));
}