Problem
求给定区间 [    l , r    ] [\;l,r\;] [l,r] 中满足下列条件的整数个数:这个数恰好等于 k k k 个互不相等的 b b b 的整数次幂之和。
例如,设 l = 15 l=15 l=15, r = 20 r=20 r=20, k = 2 k=2 k=2, b = 2 b=2 b=2,则有且仅有下列三个数满足题意: 17 = 2 4 + 2 0 17 = 2^4+2^0 17=24+20, 18 = 2 4 + 2 1 18 = 2^4+2^1 18=24+21, 20 = 2 4 + 2 2 20 = 2^4+2^2 20=24+22。
1 ≤ l ≤ r ≤ 2 31 − 1 1 ≤ l ≤ r ≤ 2^{31}-1 1≤l≤r≤231−1, 1 ≤ k ≤ 20 1 ≤ k ≤ 20 1≤k≤20, 2 ≤ b ≤ 10 2 ≤ b ≤ 10 2≤b≤10。
Solution
我们先考虑一下符合条件的数有什么特点。
比较显然的是,当这个数在 b b b 进制下 1 1 1 有 k k k 个,且其他位都是 0 0 0,那它就符合条件。
为什么不能有 2 2 2 或以上的数字出现呢?因为如果有 2 2 2,就不能满足是互不相等的 b b b 的整数次幂之和。
所以我们用数位DP,类似于 10 10 10 进制,把这个数转换成 b b b 进制后统计 1 1 1 的个数就行了。
比较简单的一道题。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int l,r,k,b,a[50],f[50][50][2];
int dp(int p,int num,bool limit)
{
if(!p) return num==k;
if(~f[p][num][limit]) return f[p][num][limit];
int i,up=limit?a[p]:(b-1),ans=0;
for(i=0;i<=up&&i<=1;++i)
ans+=dp(p-1,num+(i==1),limit&&a[p]==i);
return f[p][num][limit]=ans;
}
int solve(int x)
{
int p=0;
while(x) a[++p]=x%b,x/=b;
memset(f,-1,sizeof(f));
return dp(p,0,true);
}
int main()
{
scanf("%d%d%d%d",&l,&r,&k,&b);
printf("%d",solve(r)-solve(l-1));
return 0;
}