1081. 度的数量
题目链接
1081. 度的数量
求给定区间 \([X,Y]\) 中满足下列条件的整数个数:这个数恰好等于 \(K\) 个互不相等的 \(B\) 的整数次幂之和。
例如,设 \(X = 15, Y = 20, K = 2, B = 2\),则有且仅有下列三个数满足题意:
\(17 = 2^4 + 2^0\)
\(18 = 2^4 + 2^1\)
\(20 = 2^4 + 2^2\)
输入格式
第一行包含两个整数 \(X\) 和 \(Y\),接下来两行包含整数 \(K\) 和 \(B\)。
输出格式
只包含一个整数,表示满足条件的数的个数。
数据范围
\(1 \le X \le Y \le 2^{31}-1\),
\(1 \le K \le 20\),
\(2 \le B \le 10\)
输入样例:
15 20
2
2
输出样例:
3
解题思路
数位dp
显然,本题可以转化为前缀和计算贡献,即问题等价于计算 \(0\sim x\) 中满足条件的整数个数,不妨先将 \(x\) 的 \(B\) 进制数表示出来,从最高位开始枚举位数 \(i\),由于受条件限制,每一位只能取或不取,如果当前最高位 \(i\) 大于 \(1\),则说明这 \(i\) 位数可以任取,即贡献为 \(C_i^k\),否则如果这位为 \(1\),则有两种选择:取这位或不取这位,记录前面已经取走 \(lst\) 个 \(1\),如果当前这位不取,则后面的数可以任取,贡献为 \(C_{i-1}^{k-lst}\),注意,如果 \(k==lst\),说明此时已经全部取走,后面都不能再取了,此时也算作一种方案
- 时间复杂度:\(O(30^2+logw)\)
代码
// Problem: 度的数量
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1083/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int x,y,k,b;
int C[35][35];
int a[35],n;
int get(int x,int y)
{
n=0;
do
{
a[++n]=x%y;
x/=y;
}while(x);
int res=0,lst=0;
for(int i=n;i;i--)
{
if(a[i]>1)
{
if(k>lst)
res+=C[i][k-lst];
break;
}
else if(a[i])
{
if(k>lst)
res+=C[i-1][k-lst];
lst++;
}
if(lst==k)
{
res++;
break;
}
}
return res;
}
void init()
{
for(int i=0;i<32;i++)
for(int j=0;j<=i;j++)
if(!j)C[i][j]=1;
else
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
int main()
{
scanf("%d%d%d%d",&x,&y,&k,&b);
init();
printf("%d",get(y,b)-get(x-1,b));
return 0;
}