每一位必须是1或者0,而且1的个数为k才算1个。
dp(i,j) 表示当前处理到第i位置,且有j个1时,如果已经处理过,则返dp(i,j),否则递归。
因为最大值为1,所以在枚举当前这位的数字时,必须让它小于等于1.
代码
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int N = 1e4 + 10;
const int mod = 10007;
int l,r,k,b;
vector<int> s;
int dp[40][40];
int dfs(int n,int lead,int op,int last){
if(!n) return last == k;
if(!lead && !op && ~dp[n][last]) return dp[n][last];
int up = op ? s[n] : 9;
int res = 0;
for(int i=0;i<=min(up,1ll);i++) {
res += dfs(n-1,lead & (i == 0),op & (i == up),last + (i == 1));
}
if(!lead && !op) dp[n][last] = res;
return res;
}
int slove(int x){
memset(dp,-1,sizeof(dp));
s.clear();
s.push_back(-1);
while(x) s.push_back(x%b),x /= b;
return dfs((int)s.size()-1,1,1,0);
}
signed main(){
IOS
cin>>l>>r>>k>>b;
cout<<slove(r) - slove(l-1)<<endl;
return 0;
}