不超过N的数字组合 题解

例4. 不超过N的数字组合

本题非常简单,只是枚举每个数字是限定在 digits 数组中,而不是$0~9$。 数位之间的数字也没有限制条件。

#include<bits/stdc++.h>
using namespace std;
const int N = 31;
int memo[N]; 
int n, m;
string s, digits;
int dfs(int i, bool lim, bool ok) {
    if (i == m) return ok; // 如果填了数字,则为 1 种合法方案
    if (!lim && ok && memo[i] >= 0) return memo[i]; // 在不受到任何约束的情况下,返回记录的结果,避免重复运算
    int ret = 0;
    // 前面不填数字,那么可以跳过当前数位,也不填数字
    // lim 改为 false,因为没有填数字,位数都比 n 要短,自然不会受到 n 的约束
    // ok 仍然为 false,因为没有填任何数字
    if (!ok) ret = dfs(i + 1, false, false);
    char up = lim ? s[i] : '9'; // 根据是否受到约束,决定可以填的数字的上限
    // 注意:对于一般的题目而言,如果这里 is_num 为 false,则必须从 1 开始枚举,由于本题 digits 没有 0,所以无需处理这种情况
    for (auto &d : digits) { // 枚举要填入的数字 d
        if (d > up) break; // d 超过上限,由于 digits 是有序的,后面的 d 都会超过上限,故退出循环
            // is_limit:如果当前受到 n 的约束,且填的数字等于上限,那么后面仍然会受到 n 的约束
            // is_num 为 true,因为填了数字
        ret += dfs(i + 1, lim && (d == up), true);
    }
    if (!lim && ok) memo[i] = ret; // 在不受到任何约束的情况下,记录结果
    return ret;
}
int main(){
    cin >> digits;
    cin >> n;
    s = to_string(n);
    m = s.size();
    memset(memo, -1, sizeof memo);
    int ans = dfs(0, true, false);   //首位受限制
    cout << ans << '\n';
    return 0; 
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值