Amount of Degrees 数位DP

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Amount of Degrees 数位DP相关的知识,希望对你有一定的参考价值。

题目链接

题目
求给定区间 [ X , Y ] [X,Y] [X,Y] 中满足下列条件的整数个数:这个数恰好等于 K K K 个互不相等的 B B B 的整数次幂之和。例如,设 X = 15 , Y = 20 , K = 2 , B = 2 X=15,Y=20,K=2,B=2 X=15,Y=20,K=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

思路:
定义 d p ( n ) dp(n) dp(n)为小于等于 n n n的满足题目条件的数的个数

[ l , r ] [l,r] [l,r]区间内满足题意的数的个数为 d p ( r ) − d p ( l − 1 ) dp(r)-dp(l-1) dp(r)dp(l1),类似前缀和的思想

转化题意为:
求在目标区间内的数中化为B进制数中,数位中有K个1的个数。

初始化 i n i t init init是初始化组合数的,利用公式 C a b = C a − 1 b + C a − 1 b − 1 C_{a}^{b} = C_{a-1}^{b} + C_{a-1}^{b-1} Cab=Ca1b+Ca1b1初始化

last为前面已经选过的1的个数,res为总的个数

从最高位枚举每一位,如果当前位大于等于1,

  • 先加上当前位数为0的情况,即 C i K − l a s t C_i^{K-last} CiKlast,i表示后面剩余的位数,

  • 然后就可以加上当前位等于1的情况,即 C i K − l a s t − 1 C_i^{K-last-1} CiKlast1,当前位为1,所以要多减去1

  • 当前位等于1时要更新last

然后就是最后一位时进行特判,如果最后一位为0时,且之前的last=K,说明本身这个数也满足条件,需要加上去

#include<bits/stdc++.h>
using namespace std;
const int N = 35;

int f[N][N];
int K,B;

void init()
{
	for(int i=0;i<N;i++)
		for(int j=0;j<=i;j++)
			if(!j) f[i][j] = 1;
			else f[i][j] = f[i-1][j-1]+f[i-1][j];
}

int dp(int n)
{
	if(n==0) return 0;
	vector<int>nums;
	
	while(n) nums.push_back(n%B),n/=B;
	
	int res = 0,last = 0;
	for(int i=nums.size()-1;i>=0;i--)
	{
		int x = nums[i];
		if(x)
		{
			res += f[i][K-last];
			if(x>1)
			{
				if(K-last-1>=0)res += f[i][K-last-1];
				break;
			}
			else 
			{
				last++ ;
				if(last>K) break;
			}
		}
		if(!i && last==K) res++;
	}
	return res;
}
int  main()
{
	init();
	int l,r;
	cin>>l>>r>>K>>B;
	
	cout<<dp(r)-dp(l-1)<<'\\n';
	return 0;
}

以上是关于Amount of Degrees 数位DP的主要内容,如果未能解决你的问题,请参考以下文章

Timus Online Judge 1057. Amount of Degrees(数位dp)

Amount of Degrees(数位dp)

Amount of Degrees 数位DP

ural 1057 Amount of degrees 数位dp

URAL 1057 Amount of Degrees

Amount of Degrees