AcWing 第五场周赛
比赛链接:Here
AcWing 3726. 调整数组
签到题
void solve() {
int n; cin >> n;
int x = 0, y = 1, c;
for (int i = 0; i < n; ++i) {
cin >> c, x |= c, y &= c;
}
cout << ((x ^ y) & 1 ? "NO\n" : "YES\n");
}
AcWing 3727. 乘方相加
如果将所有的 \(v_i\) 用 kk 进制表示,则第 \(i\) 次操作就相当于是在 \(v_i\) 的第 \(i\) 位上加一。
所以如果我们能得到 a,那么所有的 \(a_i\) 的第 \(k\) 位最多只能有一个是 \(1\)。
因此我们可以枚举 \(a\) 中所有数的第 \(i\) 位,对第 \(i\) 位上的数求和,若得到的值 \(>1\),则我们不能将 \(v\) 变成 \(a\)
- \(\mathcal{O}(nlog\ a_i)\)
ll a[33];
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int _; for (cin >> _; _--;) {
int n, k;
cin >> n >> k;
for (int i = 0; i < n; ++i)cin >> a[i];
bool f = true;
for (int i = 0; i < 64 and f; ++i) {
int s = 0;
for (int j = 0; j < n; ++j) s += a[j] % k, a[j] /= k;
f &= s < 2;
}
cout << (f ? "YES\n" : "NO\n");
}
}
AcWing 3728. 城市通电
原题来自:https://codeforces.com/problemset/problem/1245/D
将题目中所有发电站和电线看成一张无向图,搭建电线看成是将图上两个点连接起来。
根据题意,最终得到的图是若干个连通块,每个连通块中有一个点建立发电站。
考虑新建一个 \(0\) 点,向 \(1∼n\) 中所有点 \(u\) 连一条长度是 \(c_u\) 的边。
那么在某个点 \(u\) 建立发电站就可以看成选择 \(0→u\) 的这条边。
那么我们要做的,就转化为:给定一张无向图,选若干条边,使得图连通。
而这恰是最小生成树。因此我们只需建图并求最小生成树即可。
时间复杂度
这里我用的是 \(kruskal\) 算法求最小生成树,时间复杂度为\(O(n^2logn)\)。
更优的算法是用 \(prim\) 算法,时间复杂度为\(O(n^2)\),但用 \(prim\) 算法不太好求具体方案,故这里选择 \(kruskal\)。
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> x(n), y(n), k(n);
for (int i = 0; i < n; ++i)
cin >> x[i] >> y[i];
vector<LL> c(n);
for (int i = 0; i < n; ++i)
cin >> c[i];
for (int i = 0; i < n; ++i)
cin >> k[i];
vector<bool> visited(n);
vector<int> parent(n, -1);
LL total = 0;
vector<int> sta;
for (int i = 0; i < n; ++i) {
int u = -1;
for (int j = 0; j < n; ++j)
if (!visited[j] && (u == -1 || c[j] < c[u]))
u = j;
visited[u] = true;
total += c[u];
if (parent[u] == -1)
sta.push_back(u);
for (int j = 0; j < n; ++j) {
if (!visited[j]) {
LL cost = 1LL * (k[u] + k[j]) * (abs(x[u] - x[j]) + abs(y[u] - y[j]));
if (cost < c[j]) {
c[j] = cost;
parent[j] = u;
}
}
}
}
cout << total << "\n";
cout << sta.size() << "\n";
for (int i : sta)
cout << i + 1 << "\n";
cout << n - sta.size() << "\n";
for (int i = 0; i < n; ++i)
if (parent[i] != -1)
cout << i + 1 << " " << parent[i] + 1 << "\n";
return 0;
}