【Ural 1057】Amount of Degrees

传送门


Problem

求给定区间 [    l , r    ] [\;l,r\;] 中满足下列条件的整数个数:这个数恰好等于 k k 个互不相等的 b b 的整数次幂之和。

例如,设 l = 15 l=15 r = 20 r=20 k = 2 k=2 b = 2 b=2 ,则有且仅有下列三个数满足题意: 17 = 2 4 + 2 0 17 = 2^4+2^0 18 = 2 4 + 2 1 18 = 2^4+2^1 20 = 2 4 + 2 2 20 = 2^4+2^2

1 l r 2 31 1 1 ≤ l ≤ r ≤ 2^{31}-1 1 k 20 1 ≤ k ≤ 20 2 b 10 2 ≤ b ≤ 10


Solution

我们先考虑一下符合条件的数有什么特点。

比较显然的是,当这个数在 b b 进制下 1 1 k k 个,且其他位都是 0 0 ,那它就符合条件。

为什么不能有 2 2 或以上的数字出现呢?因为如果有 2 2 ,就不能满足是互不相等 b b 的整数次幂之和。

所以我们用数位DP,类似于 10 10 进制,把这个数转换成 b b 进制后统计 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;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/89066315