A - Tak and Hotels (ABC Edit)
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, k, x, y;
cin >> n >> k >> x >> y;
int ans = 0;
if (n <= k) {
ans += n * x;
} else {
ans += k * x + (n - k) * y;
}
cout << ans;
return 0;
}
B - Beautiful Strings
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int st[26];
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
string s;
cin >> s;
for (auto i : s) {
st[i - 'a'] ++;
}
for (int i = 0; i < 26; i++) {
if (st[i] % 2 == 1) {
cout << "No\n";
return 0;
}
}
cout << "Yes";
return 0;
}
C - Tak and Cards
\(\rm f[i][j][k]\) 表示前 \(i\) 個物品中,選擇 \(j\) 個物品,價值之和為 \(k\) 的方案數。狀態轉移方程為:\(dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-1][k-x[i]]\) 【確保不要訪問到負數下標,下標從1開始】
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
long long f[51][51][2600], pre[1005];
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int N, A;
cin >> N >> A;
vector<int> x(N + 1);
for (int i = 1; i <= N; i++) {
cin >> x[i];
pre[i] = pre[i - 1] + x[i];
}
for (int i = 0; i <= N; i++) f[i][0][0] = 1;//初始化,啥都不選也是一種方案
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= i; j++) {
for (int k = 1; k <= pre[i]; k++) {
if (k >= x[i]) f[i][j][k] += f[i - 1][j - 1][k - x[i]];
f[i][j][k] += f[i - 1][j][k];
}
}
}
long long ans = 0;
for (int i = 1; i <= N; i++) ans += f[N][i][A * i];
cout << ans;
return 0;
}
其實這就是變形後的 \(01\) 揹包問題,可以將第一維最佳化掉,但需注意改變迴圈的遍歷順序,從小到大的狀態更新方式,若仍然順序遍歷的話,被忽略的 \(i-1\) 維度的 \(j\) 和 \(k\) 會被汙染,影響狀態轉移。因此需要逆向列舉。
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
long long f[51][2600], pre[1005];
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int N, A;
cin >> N >> A;
vector<int> x(N + 1);
for (int i = 1; i <= N; i++) {
cin >> x[i];
pre[i] = pre[i - 1] + x[i];
}
f[0][0] = 1;
for (int i = 1; i <= N; i++) {
for (int j = i; j >= 1; j--) {
for (int k = pre[i]; k >= x[i]; k--) {
f[j][k] += f[j - 1][k - x[i]];
}
}
}
long long ans = 0;
for (int i = 1; i <= N; i++) ans += f[i][A * i];
cout << ans;
return 0;
}