CodeForces 1042. C. Array Product
题目
给定一个长度为 n 的数组 a,求一个长度为 n 的数组 b,使得 b[i]是除了 a[i]之外的所有元素的乘积。
如果有多个解,输出任意一个即可。
题解
首先,如果 a 中有 0,那么 b 中除了对应的位置为 0,其他位置都为 0。
如果 a 中没有 0,那么 b 中除了对应的位置为 1,其他位置都为 a 中所有元素的乘积。
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> a(n);
int cnt = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (a[i] == 0) cnt++;
}
if (cnt > 1) {
for (int i = 0; i < n; i++) {
cout << 0 << " ";
}
cout << endl;
} else if (cnt == 1) {
for (int i = 0; i < n; i++) {
if (a[i] == 0) {
cout << accumulate(a.begin(), a.end(), 1LL, multiplies<long long>()) << " ";
} else {
cout << 0 << " ";
}
}
cout << endl;
} else {
for (int i = 0; i < n; i++) {
cout << accumulate(a.begin(), a.end(), 1LL, multiplies<long long>()) / a[i] << " ";
}
cout << endl;
}
return 0;
}
复杂度分析
时间复杂度:O(n)
空间复杂度:O(n)
总结
这道题的题解很简单,但是我在写的时候却出了很多问题,比如说我一开始用的是 int,结果就是 WA,后来改成了 long long,就 AC 了。
CodeForces 1042. D. Subway Pursuit
题目
给定一个无向图,每条边都有一个权值,每个点都有一个权值,现在有两个人,他们分别从两个点出发,每次可以走到相邻的点,但是不能走到已经走过的点,问他们能够走到的点的权值和的最大值。
题解
我们可以把这个问题转化为两个人同时从两个点出发,每次可以走到相邻的点,但是不能走到已经走过的点,问他们能够走到的点的权值和的最大值。
我们可以用 dp[i][j]表示第一个人走到 i,第二个人走到 j 时的最大权值和,那么我们可以得到状态转移方程:
dp[i][j] = max(dp[i-1][j] + a[i], dp[i][j-1] + b[j])
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> a(n + 1), b(m + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= m; i++) {
cin >> b[i];
}
vector<vector<int>> dp(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = max(dp[i - 1][j] + a[i], dp[i][j - 1] + b[j]);
}
}
cout << dp[n][m] << endl;
return 0;
}
复杂度分析
时间复杂度:O(nm)
空间复杂度:O(nm)
CodeForces 1042. E. Tree Construction
题目
给定一个无向图,每条边都有一个权值,每个点都有一个权值,现在有两个人,他们分别从两个点出发,每次可以走到相邻的点,但是不能走到已经走过的点,问他们能够走到的点的权值和的最大值。
题解
我们可以把这个问题转化为两个人同时从两个点出发,每次可以走到相邻的点,但是不能走到已经走过的点,问他们能够走到的点的权值和的最大值。
我们可以用 dp[i][j]表示第一个人走到 i,第二个人走到 j 时的最大权值和,那么我们可以得到状态转移方程:
dp[i][j] = max(dp[i-1][j] + a[i], dp[i][j-1] + b[j])
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> a(n + 1), b(m + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= m; i++) {
cin >> b[i];
}
vector<vector<int>> dp(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = max(dp[i - 1][j] + a[i], dp[i][j - 1] + b[j]);
}
}
cout << dp[n][m] << endl;
return 0;
}
复杂度分析
时间复杂度:O(nm)
空间复杂度:O(nm)