![]()
/*
此题可以转换成将10进制转成b进制后有k个1其他都为0的个数
所以用记忆化dfs
dp[pos][sum]表示将要处理第pos位,前面已有sum个一的数量
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline long long read()
{
long long f=1,ans=0;char c;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
return ans*f;
}
int x,y,k,b,dg[31],ans,dp[101][101];
long long dfs(long long pos,long long sum,long long done,long long sry)
{
// cout<<"位置:"<<pos<<" 一的个数:"<<sum<<" 小于等于:"<<done<<" 原来的数:"<<sry<<endl;
if(sum>k) return 0;
if(pos==0)
{
if(sum==k) return 1;
return 0;
}
if(done==0&&dp[pos][sum]!=-1) return dp[pos][sum];
long long end;
if(done==0) end=1;
else end=min(1,dg[pos]);
long long maxn=0;
for(long long i=0;i<=end;i++)
{
if(i==1) maxn+=dfs(pos-1,sum+1,done&&i==dg[pos],i);
else maxn+=dfs(pos-1,sum,done&&i==dg[pos],i);
}
if(done==0) dp[pos][sum]=maxn;
return maxn;
}
long long solve(long long x)
{
ans=0;memset(dg,0,sizeof(dg));
while(x!=0)
{
dg[++ans]=x%b;
x/=b;
}
// for(long long i=ans;i>=1;i--) cout<<dg[i]<<" ";
// cout<<endl;
return dfs(ans,0,1,2<<30-1);
}
int main()
{
memset(dp,-1,sizeof(dp));
x=read(),y=read(),k=read(),b=read();
cout<<solve(y)-solve(x-1);
}
View Code