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(l−1),类似前缀和的思想
转化题意为:
求在目标区间内的数中化为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=Ca−1b+Ca−1b−1初始化
last
为前面已经选过的1的个数,res
为总的个数
从最高位枚举每一位,如果当前位大于等于1,
-
先加上当前位数为0的情况,即 C i K − l a s t C_i^{K-last} CiK−last,
i
表示后面剩余的位数, -
然后就可以加上当前位等于1的情况,即 C i K − l a s t − 1 C_i^{K-last-1} CiK−last−1,当前位为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)