AcWing第6场周赛题解
A. AcWing 3733. 去掉一个元素
题目链接:https://www.acwing.com/problem/content/3736/
题目大意:问共有多少个元素满足,在去掉该元素后,剩余元素的相加之和为一个偶数(注意,0 也算偶数)。
解题思路:若和为奇数,答案为奇数个数;若和为偶数,答案为偶数个数。
示例程序:
#include <bits/stdc++.h>
using namespace std;
int n, a, sum, cnt;
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a;
sum += a;
if (a % 2) cnt++;
}
if (sum%2) cout << cnt << endl;
else cout << n - cnt << endl;
return 0;
}
B. AcWing 3734. 求和
题目链接:https://www.acwing.com/problem/content/3737/
题目大意:按照题目描述求区间内所有数字的和。
解题思路:定义只包含 4 或 7 的数位 Lucky number,则我们其实可以直接由当前的数跳转到下一个 Lucky number,然后批量求和。Lucky number 其实没有多少,所以可以基于这样的思路进行模拟。
示例程序:
#include <bits/stdc++.h>
using namespace std;
long long nxt(long long a) {
long long t = 1, b = 0;
while (a) {
if (a % 10 == 4) {
return (a + 3) * t + b;
}
b = b * 10 + 4;
a /= 10;
t *= 10;
}
return b * 10 + 4;
}
long long l, r, sum;
int main() {
cin >> l >> r;
for (long long a = 4; l <= r; a = nxt(a)) {
if (a >= l) {
long long p = min(a, r);
sum += (p - l + 1) * a;
l = p + 1;
}
}
cout << sum << endl;
return 0;
}
C. AcWing 3735. 构造完全图
题目链接:https://www.acwing.com/problem/content/3738/
题目大意:每次操作时,可以选择其中一个点,找到所有和它直接相连的点,使这些点两两之间连边(若两点之间已经存在边,则无需重复连接)。问,至少多少次操作以后,可以将整个图变为一个完全图?
解题思路:状压dp,基于一个贪心思想,思想来自于 题解视频 ,但是贪心思想的证明没有完全搞明白。每次选择一个点,则所有与这个点邻接的点都会加入这个点所在的极大连通子图,形成一个更大的极大连通子图。由于数据量比较小所以可以状态压缩。
示例程序参考了 我已经不想再做刺客了大佬的代码
示例程序:
#include <bits/stdc++.h>
using namespace std;
int f[1<<22], n, m, b[22];
pair<int, int> step[1<<22]; // {前一个状态, 选择的点}
int main() {
cin >> n >> m;
if (m == n*(n-1)/2) { // 本身就是一个团
cout << 0 << endl;
return 0;
}
while (m--) {
int u, v;
cin >> u >> v;
u--, v--;
b[u] |= (1<<v);
b[v] |= (1<<u);
}
memset(f, 0x3f, sizeof(f));
for (int i = 0; i < n; i++) {
b[i] |= (1<<i);
f[b[i]] = 1;
step[b[i]] = {0, i};
}
for (int st = 0; st < (1<<n); st++) {
if (f[st] == 0x3f3f3f3f) continue;
for (int i = 0; i < n; i++) {
if (st & (1<<i)) {
int st2 = st | b[i];
if (f[st2] > f[st] + 1) {
f[st2] = f[st] + 1;
step[st2] = {st, i};
}
}
}
}
int p = (1<<n) - 1;
cout << f[p] << endl;
while (p) {
cout << step[p].second + 1 << " ";
p = step[p].first;
}
return 0;
}