容斥原理
不定方程非负整数解计数
\(f(x)\) 为 \(a_0\cdot b_0+a_1\cdot b_1+…a_k\cdot b_k=x\) 的所有方案数,\(a_i\) 为常数,\(b_i\) 为变量
例题
P1450 [HAOI2008] 硬币购物 - 洛谷
先做完全背包处理方案数。
然后二进制枚举,第 \(i\) 枚硬币超过数量限制(恰好用了 \(d[i]+1\) 枚),进行容斥
从而计算出超过数量上限的方案数。
答案为 总方案数减去超过数量的方案数。
代码
| C++ |
|---|
| using i64 = long long;
i64 f[100005];
int main() {
f[0] = 1;
vector<int> c(4);
for (int i = 0 ; i < 4 ; i++) {
cin >> c[i];
for (int j = 0 ; j <= 100000 ; j++) {
if (j - c[i] >= 0) {
f[j] += f[j - c[i]];
}
}
}
int n;
cin >> n;
for (int i = 0 ; i < n ; i++) {
vector<int> d(4);
i64 s;
for (int j = 0 ; j < 4 ; j++) {
cin >> d[j];
}
cin >> s;
i64 res = 0;
for (int i = 1 ; i < 1 << 4 ; i++) {
i64 m = s;
int sign = -1;
for (int j = 0 ; j < 4 ; j++) {
if (i & 1 << j) {
m -= (d[j] + 1) * c[j];
sign = -sign;
}
}
if (m >= 0) {
res += sign * f[m];
}
}
cout << f[s] - res << "\n";
}
return 0;
}
|