【题解】1585: 【例 1】Amount of Degrees

\(Description:\)

给出一个区间 \([L,R]\) ,要求这区间内满足由 \(k\) 个不同的 \(B\) 的幂次的数组成

\(Sample\) \(Input:\)

15 20 2 2

\(Sample\) \(Output:\)

3

\(Solution:\)

首先这题可以写暴力,过50分,爽快。

对于暴力考虑剪枝,很简单,倒着搜索,每次让枚举范围变小,可以过78分。

正解肯定是数位dp,考试的时候也不是没想到,就是没理解一个性质:

一个 \(B\) 进制数最高位为 \(1\) 那么不管后面怎么填都不会比他大。

同时这题还要注意只有当枚举范围变成 \(digit\) 是才算 \(limit\)

从今开始改善码风~~

#include<cstdio>
#include<cstring>
#include<algorithm>

using std::min;
using std::scanf;
using std::printf;
using std::memset;

typedef long long LL;
const int N=35,M=25;

LL l,r,B;
int k;
int digit[N];
LL  f[N][M];
inline LL dfs(int len,int num,bool limit){
    if(num>k) return 0;
    if(len+num<k) return 0;
    if(len==0) return num==k;
    if(!limit && f[len][num]!=-1) return f[len][num];
    int up_bound=(limit && !digit[len])?digit[len]:1;
    LL ret=0;
    for(int i=0;i<=up_bound;++i)
        ret+=dfs(len-1,num+(i==1),limit&&(i==digit[len]));
    if(!limit) f[len][num]=ret;
    return ret;
}
inline LL solve(LL x){
    int cnt=0;
    memset(f,-1,sizeof(f));
    while(x>0) digit[++cnt]=x%B,x/=B;
    return dfs(cnt,0,true);
}
int main(){
    scanf("%lld%lld%d%lld",&l,&r,&k,&B);
    printf("%lld\n",solve(r)-solve(l-1));
    return 0;
}

转载于:https://www.cnblogs.com/JCNL666/p/10765213.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值