AcWing第5场周赛题解

A. AcWing 3726. 调整数组

题目链接:https://www.acwing.com/problem/content/3729/

题目大意:判断若干次 \(+2\) 操作能否最终让所有值都相等。

解题思路:\(n\) 个数奇偶性相同就行。

示例程序:

#include <bits/stdc++.h>
using namespace std;

int T, n, a[101];

bool check() {
    for (int i = 1; i < n; i++)
        if (a[0]%2 != a[i]%2)
            return false;
    return true;
}

int main() {
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 0; i < n; i++) cin >> a[i];
        puts(check() ? "YES" : "NO");
    }
    return 0;
}

B. AcWing 3727. 乘方相加

题目链接:https://www.acwing.com/problem/content/3730/

题目大意:求由 \(k^0, k^1, k^2, \ldots\) 能否加成一个数列 \(a\)

解题思路:贪心。由于 \(k \ge 2\),则 \(2^0 + 2^1 + 2^2 + \ldots + 2^{k-1} \lt 2^k\),所以我们可以从大到小判断 \(2^k\) 和当前数列中最大的那个数,如果最大的那个数 \(\ge 2^k\),则最大的那个数减去 \(2^k\),这样如果最终能都变成 \(0\),则说明 YES;否则 NO。(实现是使用优先队列即时获得及更新最大的那个数)

示例程序:

#include <bits/stdc++.h>
using namespace std;

int T, n, k;
priority_queue<long long> pq;
long long a;

bool check() {
    while (!pq.empty()) pq.pop();
    cin >> n >> k;
    while (n--) {
        cin >> a;
        if (a > 0) pq.push(a);
    }
    long long t = 1;
    while (t <= (1LL<<60) / k) t *= k;
    for (; t >= 1 && !pq.empty(); t /= k) {
        long long u = pq.top();
        if (u >= t) {
            pq.pop();
            u -= t;
            if (u > 0) pq.push(u);
        }
    }
    return pq.empty();
}

int main() {
    cin >> T;
    while (T--) {
        puts(check() ? "YES" : "NO");
    }
    return 0;
}

C. AcWing 3728. 城市通电

题目链接:https://www.acwing.com/problem/content/3731/

题目大意:通过建立发电站和搭建电线的方式给每座城市都通电。求最小花费。

解题思路:最小生成树。思路是额外增加一个超级点 \(s\)\(s\) 向每个点 \(i\) 连一条权值为 \(c_i\) 的边,然后求 MST。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int n, pre[maxn];
long long g[maxn][maxn], x[maxn], y[maxn], cost[maxn], k[maxn];
bool vis[maxn];
vector<int> v1;
vector<pair<int, int>> v2;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> x[i] >> y[i];
    for (int i = 1; i <= n; i++)
        cin >> g[0][i]; // g[i][0]可以赋值但是我这里用不到
    for (int i = 1; i <= n; i++)
        cin >> k[i];
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            g[i][j] = (abs(x[i]-x[j]) + abs(y[i]-y[j])) * (k[i] + k[j]);
    memset(cost, 0x3f, sizeof(cost));
    cost[0] = 0;
    long long ans = 0;
    for (int i = 0; i <= n; i++) {
        int u = -1;
        for (int j = 0; j <= n; j++)
            if (!vis[j] && (u==-1 || cost[u] > cost[j]))
                u = j;
        vis[u] = true;
        ans += cost[u];
        // printf("find u = %d , cost[u] = %lld, pre[u] = %d\n", u, cost[u], pre[u]);
        for (int j = 1; j <= n; j++)
            if (!vis[j] && g[u][j] < cost[j]) {
                cost[j] = g[u][j];
                pre[j] = u;
            }
    }
    for (int i = 1; i <= n; i++) {
        if (!pre[i]) v1.push_back(i);
        else v2.push_back({pre[i], i});
    }
    cout << ans << endl;
    int sz = v1.size();
    cout << sz << endl;
    for (int i = 0; i < sz; i++) {
        if (i) cout << " ";
        cout << v1[i];
    }
    cout << endl;
    sz = v2.size();
    cout << sz << endl;
    for (int i = 0; i < sz; i++)
        cout << v2[i].first << " " << v2[i].second << endl;
    return 0;
}
posted @ 2022-04-07 20:42  quanjun  阅读(23)  评论(0)    收藏  举报