描述
求给定区间[X,Y]中满足下列条件的整数个数:这个数恰好等于K个互不相等的B的整数次幂之和。
例如,设X=15,Y=20,K=2,B=2,则有且仅有下列三个数满足题意:
17 = 24+20,
18 = 24+21,
20 = 24+22。
输入
第一行包含两个整数X和Y。接下来两行包含整数K和B。
输出
只包含一个整数,表示满足条件的数的个数。
样例输入 [复制]
15 20
2
2
样例输出 [复制]
3
数据规模:
1 ≤ X ≤ Y ≤ 2^31−1,1 ≤ K ≤ 20, 2 ≤ B ≤ 10
思路:
自己写的第一道数位dp ,纪念一下。。
其实进制拆分不是那么难想, 注意 互不相同: 每一位都是0或1 相当于二进制了。。
#include<queue>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<string>
#include<algorithm>
#define pf printf
#define sf scanf
using namespace std;
int h[31];
int f[40][35],K,X,Y,B;
inline void pre(){
f[0][0]=1;f[0][1]=1;
for(int i=1;i<=31;++i){
f[i][0]=1;
for(int j=1;j<=i+1;++j)f[i][j]=f[i-1][j-1]+f[i-1][j];
}
}
inline int solve(int x){
int top=-1;
while(x){
int p=x%B;
x/=B;
h[++top]=p;
}
int tot=0,ans=0;
for(int i=top;i>=0;--i){
if(h[i]==1){
++tot;if(tot>K+1)break;
if(i>0)ans+=f[i-1][K-tot+1];
//注意,此处默认当前位为 0 所以 要+1
}
else if(h[i]>1){
ans+=f[i][K-tot];
return ans;
}
}
if(tot==K)++ans;
return ans;
}
signed main (){
sf("%d%d%d%d",&X,&Y,&K,&B);
pre();
--X;
int ans=solve(Y)-solve(X);
printf("%d",ans);
return 0;
}