Codeforces Round #677 (Div. 3) (A - E题题)
1433A. Boring Apartments
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
string s;
cin >> s;
int l = s.length();
int ans = 10 * (s[0] - '0' - 1) + (l * (l + 1)) / 2;
cout << ans << endl;
}
}
1433B. Yet Another Bookshelf
题意: 有一个\(n\)大小的一维书架,从\(1\)到\(n\)开始编号,给出了书架的相关信息,即\(a_i\)为1 11则代表有书,\(a_i\) 为 0 则代表没有书。现在你可以进行一次操作,选择一个区间段 $[ l : r ] $,进行其中任意一个:
- 将该区间所有有书的格子向右移。移的前题是 \(r + 1 <= n , a_{r + 1} = 1\)
- 将该区间所有有书的格子向左移。移的前题是\(l - 1 >= 1,a_{l - 1} = 1\)
问你至少需要进行多少次操作次数才可以使得书架上的书是连续放置的。
仔细观察一下,我们只要找到第一个 1 和 最后一个 1的下标, 再遍历这个区间寻找0的个数
void solve() {
cin >> n;
int a[n + 1];
for (int i = 1; i <= n; ++i) cin >> a[i];
int f1 = -1, f2 = -1;
for (int i = 1; i <= n; ++i)
if (a[i]) {
f1 = i;break;
}
for (int i = n; i > 0; i--)
if (a[i]) {
f2 = i;break;
}
int cnt = 0;
for (int i = f1 + 1; i <= f2; ++i)
if (!a[i]) cnt++;
cout << cnt << endl;
}
1433C. Dominant Piranha
题意:
在一个鱼缸中有\(n\)条食人鱼,它们从\(1\)到\(n\)依次编号排列,其中尺寸为 \(a_i\),有这样的规则,若食人鱼的尺寸大于旁边的一条食人鱼的尺寸,那么这条食人鱼就可以吃了它并尺寸+ 1。请你找到一个优势食人鱼。(即经过一系列操作,这条食人鱼是最终活下来的食人鱼。)
看半天题,被样例骗了,我们不一定要使弱者变强,只需要使强者更强即可(贪心思想)
void solve() {
cin >> n;
vector<int> a(n);
int idx = -1, mx = -1;
for (auto& it : a) {
cin >> it;
mx = max(mx, it);
}
for (int i = 0; i < n; ++i) {
if (a[i] != mx) continue;
if (i - 1 >= 0 && a[i - 1] != mx) idx = i + 1;
if (i + 1 < n && a[i + 1] != mx) idx = i + 1;
}
cout << idx << endl;
}
1433D - Districts Connection
有\(n\)个区,每个区都属于一个帮,现在你需要用\(n − 1\)条道路连连接这些区,要求所连的直接区不能属于一个帮,可以使用中间点来连接。
如果所有地区都属于同一个帮派,则答案为“否”。 否则,答案始终是“是”(是的,就像前面的问题一样)。 如何构造? 让我们选择第一个“根”作为地区1,并将a1≠ai的所有此类地区i连接到地区1。因此,所有剩余的未连接地区都受团伙a1的控制。 让我们找到ai≠ai的任何地区,然后将帮派a1的所有其余地区连接到该地区。 因为我们至少有两个不同的帮派,所以这个地区一直存在,因为它的帮派不是a1,所以它与其余结构相连。 因此,满足所有条件。
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n);
for (auto &it : a) cin >> it;
vector<pair<int, int>> res;
int idx = -1;
for (int i = 1; i < n; ++i) {
if (a[i] != a[0]) {
idx = i;
res.push_back({1, i + 1});
}
}
if (idx == -1) {
cout << "NO" << endl;
continue;
}
for (int i = 1; i < n; ++i) {
if (a[i] == a[0]) {
res.push_back({idx + 1, i + 1});
}
}
cout << "YES" << endl;
for (auto [x, y] : res) cout << x << " " << y << endl;
}
}
1433E - Two Round Dances
首先,我们需要选择一组 \(\frac n2\)个人参加第一轮舞蹈(另一半参加第二轮)。 做到这一点的方法数是\(\dbinom{n}{\frac n 2}\)。 然后,我们需要在两种轮舞中都设置一些人的顺序,但是我们不想忘记轮换(因为轮换可以使我们多次计数相同的方式)。 因此,将人安排在一轮舞中的方式为\((\frac n 2-1)\)! 这是正确的,因为我们只是“固定”了谁将成为第一位来回跳舞,并以各种可能的顺序安排其他人。 因此,我们需要将初始答案乘以该值两次,因为我们有两个回合舞。 最后,我们必须将答案除以2,因为我们计算了“有序”对(即,我们区分了类型(x,y)和(y,x)的对,但不必这样做。 因此,最终答案是\(\dbinom{n}{\frac n 2}\)⋅\((\frac n 2-1)\)!⋅\((\frac n 2-1)\)! 除以2。该公式可以简化为\(\frac{n!}{\frac{n^2}2⋅2}\)。
#include <bits/stdc++.h>
using namespace std;
const int N = 21;
long long f[N];
int main() {
int n;
cin >> n;
f[0] = 1;
for (int i = 1; i < N; ++i) {
f[i] = f[i - 1] * i;
}
long long ans = f[n] / f[n / 2] / f[n / 2];
ans = ans * f[n / 2 - 1];
ans = ans * f[n / 2 - 1];
ans /= 2;
cout << ans << endl;
}
1433F - Zero Remainder Sum
待补、先贴下dalao代码
Code
#include <bits/stdc++.h>
using namespace std;
#define forn(i, n) for (int i = 0; i < int(n); ++i)
const int N = 70;
const int INF = 1e9;
int a[N][N];
int dp[N][N][N][N];
int main() {
int n, m, k;
cin >> n >> m >> k;
forn(i, n) forn(j, m) cin >> a[i][j];
forn(i, N) forn(j, N) forn(cnt, N) forn(rem, N) dp[i][j][cnt][rem] = -INF;
dp[0][0][0][0] = 0;
forn(i, n) forn(j, m) forn(cnt, m / 2 + 1) forn(rem, k) {
if (dp[i][j][cnt][rem] == -INF) continue;
int ni = (j == m - 1 ? i + 1 : i);
int nj = (j == m - 1 ? 0 : j + 1);
if (i != ni) {
dp[ni][nj][0][rem] = max(dp[ni][nj][0][rem], dp[i][j][cnt][rem]);
} else {
dp[ni][nj][cnt][rem] =
max(dp[ni][nj][cnt][rem], dp[i][j][cnt][rem]);
}
if (cnt + 1 <= m / 2) {
int nrem = (rem + a[i][j]) % k;
if (i != ni) {
dp[ni][nj][0][nrem] =
max(dp[ni][nj][0][nrem], dp[i][j][cnt][rem] + a[i][j]);
} else {
dp[ni][nj][cnt + 1][nrem] = max(dp[ni][nj][cnt + 1][nrem],
dp[i][j][cnt][rem] + a[i][j]);
}
}
}
cout << max(0, dp[n][0][0][0]) << endl;
}
1433G - Reducing Delivery Cost
待补、先贴下dalao代码
Code
#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
int n;
vector> d;
vector>> g;
void dijkstra(int s, vector &d) {
d = vector(n, INF);
d[s] = 0;
set> st;
st.insert({d[s], s});
while (!st.empty()) {
int v = st.begin()->second;
st.erase(st.begin());
for (auto [to, w] : g[v]) {
if (d[to] > d[v] + w) {
auto it = st.find({d[to], to});
if (it != st.end()) st.erase(it);
d[to] = d[v] + w;
st.insert({d[to], to});
}
}
}
}
int main() {
int m, k;
cin >> n >> m >> k;
g = vector>>(n);
for (int i = 0; i < m; ++i) {
int x, y, w;
cin >> x >> y >> w;
--x, --y;
g[x].push_back({y, w});
g[y].push_back({x, w});
}
vector> r(k);
for (auto &[a, b] : r) {
cin >> a >> b;
--a, --b;
}
d = vector>(n);
for (int v = 0; v < n; ++v) {
dijkstra(v, d[v]);
}
int ans = INF;
for (int v = 0; v < n; ++v) {
for (auto [to, w] : g[v]) {
int cur = 0;
for (auto [a, b] : r) {
cur += min({d[a][b], d[a][v] + d[to][b], d[a][to] + d[v][b]});
}
ans = min(ans, cur);
}
}
cout << ans << endl;
}