AcWing 1081. 度的数量

参考题目:AcWing 1081. 度的数量

题意

求在给定区间内,满足以B进制表示的数中,恰好有K位是1的数的个数。

分析

f数组:存放预处理出的组合数。

  • f[i][j],表示从i个数中选出j个数的个数。(组合数)

dp函数:求出0 ~ n中满足条件的数的个数,前缀和的思想。

  • num数组:存放n的每一位数字。

  • resdp函数的结果。

  • last:已经放1的位的个数。

代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 35;

int K, B;
int f[N][N]; // 组合数。

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] + f[i - 1][j - 1];
        }
    }
}

int dp(int n)
{
	// 边界条件特判。
    if (!n) return n;
    
    // 将n转换为B进制。
    vector<int> num;
    while (n) num.push_back(n % B), n /= B;
    
    int res = 0;
    int last = 0;
    for (int i = num.size() - 1; i >= 0; i -- )
    {
        int x = num[i];
        
        // 左边的情况满足 0 ~ x - 1。
        if (x)
        {
        	// 不选1的情况。
            res += f[i][K - last];
            
            // 选1的情况,因为是0 ~ x - 1,所以x > 1才能选1。
            if (x > 1)
            {
                if (K - last - 1 >= 0) res += f[i][K - last - 1];
                // 如果x > 1,那么不存在右边的情况。
                break;
            }
            else // x = 1的情况
            {
                last ++ ; // 选1的位数需要加一。
                if (last > K) break; // 如果放的1多于限制条件的情况。
            }
        }
        
        // 如果n是符合条件的数的情况。
        if (!i && K == last) res ++ ;
    }
    return res;
}

int main()
{
    init();
    
    int l, r;
    cin >> l >> r >> K >> B;
    
    cout << dp(r) - dp(l - 1) << endl;
    
    return 0;
}

参考资料:
https://www.acwing.com/solution/content/34003/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值