[H数学] lc3257. 放三个车的价值之和最大 II(组合数学+记忆化搜索+好题)

1. 题目来源

链接:3154. 到达第 K 级台阶的方案数

2. 题目解析

很不错的题目哈。如果想到是 dp 的话,确实一时半会还弄不出来,因为这个数组范围不确定,都不知道开多大。

记忆化搜索的话,配合哈希表存储状态,是可以做,但也需要一定的技巧,如灵神记忆化搜索中写的将状态压缩到 LL 中。一些边界情况又要考虑清楚。估计也就是练练手就忘的程度。

正解还得是组合数学。


思路:

  • 因为操作1 限制较大。操作2 没有限制,简单推一下公式就可以知道如果做 n 次操作 2,就可以向前跳 2 n − 1 2^n-1 2n1 个台阶。此为上界。
  • 此时可以操作 n+1 次操作 1,即可以回跳 2 n − 1 − n − 1 = 2 n − n − 2 2^n-1-n-1=2^n-n-2 2n1n1=2nn2 个台阶位置。此为下界。
  • 且因为初始化在台阶1上,所以,n 次操作可到达的台阶位置为 [ 2 n − n − 1 , 2 n ] [2^n-n-1, 2^n] [2nn1,2n]
  • 那么如果当 k 在这个台阶位置内的话,只需要 2 n − k 2^n-k 2nk 次操作1,即可到达 k 位置。这就是一种方案。
  • 此时相当于有 n + 1 n+1 n+1 个空位,选择其中的 2 n − k 2^n-k 2nk 个空位进行填充的方案数。即为组合数 ( 2 n − k n + 1 ) \binom{2^n-k}{n+1} (n+12nk)

这里 k 取值范围较小,所以可以在 int 范围内枚举完毕。但还是需要注意在枚举 2^n 的时候爆 int 的问题…乘到最后一个位置的时候,将爆 int…


  • 时间复杂度 O ( l o g k ) O(logk) O(logk)
  • 空间复杂度 O ( 1 ) O(1) O(1)

class Solution {
public:
    typedef long long LL;
    int C(int a, int b) {       // 组合数简单计算公式
        LL res = 1;
        for (int i = 1; i <= b; i ++ ) res = res * (a - i + 1) / i;

        return res; 
    }
  
    int waysToReachStair(int k) {
        int res = 0;
        LL pow2 = 1;    // 注意在这开 LL 就行了,不然下面越界
        // 枚举操作 2 的次数。k 需要落在 2^n-n-1 ~ 2^n 这个范围内
        // 其中,操作 1 的次数即为 2^n-k 次
        for (int i = 0; i <= 30; i ++ ) {   // 这个等号其实可以不用,这样子 pow2 也不需要开 LL 了
            if (k >= pow2 - i - 1 && k <= pow2) res += C(i + 1, pow2 - k);
            pow2 *= 2;
        }
        return res; 
    }
};
  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值