1 条题解

  • 0
    @ 2077-8-30 3:39:04

    练86.3 货币系统

    解题思路

    零钱组合计数,dp[0]=1。外层按面值逐种处理,内层金额从coin升序到m,dp[s]+=dp[s-coin]。外层币种顺序固定避免把同组合的不同取钱次序重复计算。

    正确性说明

    处理当前币种时,不用它的方案已在dp[s],至少用一枚的方案可由当前轮dp[s-c]再加一枚得到。升序允许重复使用,币种外层保证组合只计一次。

    易错点

    本题输入格式漏写后续面值,但样例明确需读取n个面值;方案数用字符串大整数防溢出。

    复杂度

    最大计数D位,时间O(nmD),空间O(mD)。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    
    string addBig(string a, string b) {
        string s;
        int i = a.size() - 1, j = b.size() - 1, c = 0;
        while (i >= 0 || j >= 0 || c) {
            int v = c;
            if (i >= 0)
                v += a[i--] - '0';
            if (j >= 0)
                v += b[j--] - '0';
            s += char('0' + v % 10);
            c = v / 10;
        }
        while (s.size() > 1 && s.back() == '0')
            s.pop_back();
        reverse(s.begin(), s.end());
        return s;
    }
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n, m;
        cin >> n >> m;
        vector<int> coin(n);
        for (int &x : coin)
            cin >> x;
        vector<string> dp(m + 1, "0");
        dp[0] = "1";
        for (int c : coin)
            for (int s = c; s <= m; s++)
                dp[s] = addBig(dp[s], dp[s - c]);
        cout << dp[m] << "\n";
        return 0;
    }
    
    • 1

    信息

    ID
    539
    时间
    1000ms
    内存
    128MiB
    难度
    普及
    标签
    递交数
    0
    已通过
    0
    上传者