Description
一共有 $4$ 种硬币。面值分别为 $c_1,c_2,c_3,c_4$ 。某人去商店买东西,去了 $tot$ 次。每次带 $d_i$ 枚 $c_i$ 硬币,买 $s$ 的价值的东西。请问每次有多少种付款方法。
Solution
考虑没有 $d$ 的限制,直接完全背包。$dp_i$ 表示 $i$ 这个面值用 $c_1…c_4$ 凑有多少种方法
加上限制就容斥枚举 $16$ 种情况表示哪几种面值的性质没有被满足。
然后可以观察到,如果对于 $i$ 不满足限制,方案数就是 $dp_{s-(d_i+1)c_i}$
所以归纳一下就是
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
#include <bits/stdc++.h> #define int long long #define ll long long #define RG register #define rep(i, l, r) for(RG int i = l; i <= r; i++) #define per(i, r, l) for(RG int i = r; i >= l; i--) using namespace std; void INIT() { ios :: sync_with_stdio(false); cin.tie(0); } const int N = 100100; int n, c[5], d[5]; int dp[N]; signed main() { INIT(); dp[0] = 1; rep(i, 1, 4) cin >> c[i]; cin >> n; rep(j, 1, 4) rep(i, 0, 100000) if(i + c[j] <= 100000) dp[i + c[j]] += dp[i]; rep(i, 1, n) { int s; int ans = 0; rep(j, 1, 4) cin >> d[j]; cin >> s; rep(j, 0, 15) { int s1 = 0, s2 = s; rep(t, 1, 4) if(j & (1 << (t - 1))) { s1++; s2 -= (d[t] + 1) * c[t]; } ans += ((s1 & 1) ? -1 : 1) * (s2 >= 0 ? dp[s2] : 0); } cout << ans << endl; } return 0; }
|