0%

【题解】AcWing 第71场周赛题解

A. 三个整数

题目链接:AcWing 4621. 三个整数

一眼题,由于保证了一定有解,所以只需要保证 \(x,y\) 尽量大, \(z\) 尽量小即可。即 \(x\)\(b\)\(y\)\(c\)\(z\)\(c\)

1
2
3
4
5
6
7
#include <iostream>
int a, b, c;
int main() {
scanf("%d%d%d", &a, &b, &c);
printf("%d %d %d", b, c, c);
return 0;
}

B. 整数拆分

题目链接:AcWing 4622. 整数拆分

我们知道,素数的定义就是因数只有 \(1\) 和它本身。所以,我们要将 \(n\) 尽量拆分成由若干个素数之和。

根据哥德巴赫猜想,每一个不小于 \(6\) 的偶数都是两个奇素数之和,每一个不小于 \(9\) 的奇数都是三个奇素数之和。所以,当 \(n\) 不是素数时,最优解一定为两个或三个的素数之和。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 我的代码
#include <iostream>
const int N = 1e6 + 9;
int pc, rP[N];
bool isP[N];
void Eratos() {
for (int i = 2; i < N; i++)
isP[i] = true;
for (long long i = 2; i < N; i++) {
if (isP[i]) {
rP[++pc] = i;
for (long long j = i * i; j < N; j += i)
isP[j] = false;
}
}
}
bool isPrime(long long x) {
for (long long i = 1; 1ll*rP[i]*rP[i]<=x and i<=pc; i++)
if (x % rP[i] == 0)
return false;
return true;
}
int main() {
Eratos();
int n;
scanf("%d", &n);
if (isPrime(n)) puts("1");
else {
for (int i = 1; rP[i]<=n/2 and i<=pc; i++) {
if (isPrime(n - rP[i])) {
puts("2");
return 0;
}
}
puts("3");
}
return 0;
}

(听了 y 总讲解才发现这里都不用筛素数)

C. 买糖果

题目链接:AcWing 4623. 买糖果

当时在这道题上卡了好久,听了 y 总讲解后才知道直接暴力就能过

没有什么技术含量的暴力题(我居然没过),直接看代码注释吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
const int N = 2e5 + 9;
int n, a[N];
long long T, res;
int main() {
scanf("%d%lld", &n, &T);
for (int i = 1; i <= n; i++)
scanf("%d", a + i);
while (true) {
long long sum = 0, cnt = 0;
// sum 累加这一轮买糖果所需要花费的钱
// cnt 统计这一轮能买多少颗糖果
for (int i = 1; i <= n; i++)
if (sum + a[i] <= T) { // 如果当前这一轮还能买得起这家糖果店的糖,那就累加起来
sum += a[i];
cnt++;
}
if (!cnt) break; // 已经买不起任何糖果了,直接退出循环
res += T / sum * cnt;
// T / sum: 这一轮能重复多少次
// 比如说,你有 114514 元钱,糖果的价钱依次是 1 1 4 5 1 4
// 则与第一轮的购买方案相同的情况有 114514 / (1 + 1 + 4 + 5 + 1 + 4) 种
// 所以,总共就可以购买 114514 / (1 + 1 + 4 + 5 + 1 + 4) * 6 颗糖果
T %= sum;
// 重复完若干轮后,你还有多少钱
}
printf("%lld", res);
return 0;
}

这里需要再补充一下时间复杂度的问题。

我一开始也想到了这样暴力,但是我认为这样一定会 TLE(看上去的时间复杂度在 \(\mathcal{O}(N^2)\) 级别,会超时),所以我没有这么写。但是,通过仔细分析就可以发现,当我们每一轮执行完 T %= sum 后,\(T\) 一定会至少折半。

这里我们分两种情况讨论:第一种是 \(\frac{T}{2} < sum\leq T\),第二种是 \(sum\leq \frac{T}{2}\)

如果是第一种,那么模完后的结果为 T - sum,结果一定小于 \(\frac{T}{2}\)

如果是第二种,那么模完后的结果也显然小于 \(\frac{T}{2}\)

所以,这里的时间复杂度其实是 \(\mathcal{O}(n\ log\ T)\) 的,最大计算次数为 \(2\times 10^5\times 60 = 1.2\times 10^7\),可以通过。