acwing1081. 度的数量

求给定区间 [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。

输出格式

只包含一个整数,表示满足条件的数的个数。

数据范围
1≤X≤Y≤231−1
,
1≤K≤20
,
2≤B≤10

输入样例:

15 20
2
2

输出样例:

3

注意此题在dfs的过程中,更新lim,不能和普通的十进制类似,对于普通的十进制,我们写成:

limit && i == a[pos]
limit && i == up

但对于此题,我们是枚举的每一位是否为 0 / 1 0/1 0/1,所以lim的限制只能使用第一种形式。lim是对于我们枚举原数位进行限制,但此处对于上界的确定:

int up=lim ? min(a[pos],1) : 1 ;

所以只能使用第一种形式

#include 

using namespace std;
const int N = 1e6 + 5;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<ll, 3> p3;
int mod = 1e9 + 7;
const int maxv = 4e6 + 5;

ll dp[200][200];
int a[200];

int l,r,k,b;


ll dfs(int pos,int lim,int cnt)
{
	if(!pos) return cnt==k;
	if(!lim&&dp[pos][cnt]!=-1) return dp[pos][cnt];
	ll res=0;
	int up=lim ? min(a[pos],1) : 1 ;
	for(int i=0;i<=up;i++){
		if(cnt+i>k) continue;
		res+=dfs(pos-1,lim&&i==a[pos],cnt+i);
	}
	if(!lim) dp[pos][cnt]=res;
	return res;
}

ll get(ll x)
{
	int len = 0;
	while (x)
	{
		a[++len] = x % b;
		x /= b;
	}
	return dfs(len,1,0);
}

void solve()
{
	cin>>l>>r>>k>>b;
	ll ans=get(r)-get(l-1);
	cout<<ans<<endl;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	t = 1;
	// cin >> t;
	memset(dp, -1, sizeof dp);
	while (t--)
	{
		solve();
	}
	system("pause");
	return 0;
}

你可能感兴趣的:(算法,深度优先)