A. 三个整数
题目链接:AcWing 4621. 三个整数
一眼题,由于保证了一定有解,所以只需要保证 x , y x,y x,y 尽量大, z z z 尽量小即可。即 x x x 取 b b b, y y y 取 c c c, z z z 取 c c c。
#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 1 1 和它本身。所以,我们要将 n n n 尽量拆分成由若干个素数之和。
根据哥德巴赫猜想,每一个不小于 6 6 6 的偶数都是两个奇素数之和,每一个不小于 9 9 9 的奇数都是三个奇素数之和。所以,当 n n n 不是素数时,最优解一定为两个或三个的素数之和。
// 我的代码
#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 总讲解后才知道直接暴力就能过
没有什么技术含量的暴力题~~(我居然没过)~~,直接看代码注释吧。
#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(看上去的时间复杂度在
O
(
N
2
)
\mathcal{O}(N^2)
O(N2) 级别,会超时),所以我没有这么写。但是,通过仔细分析就可以发现,当我们每一轮执行完 T %= sum
后,
T
T
T 一定会至少折半。
这里我们分两种情况讨论:第一种是 T 2 < s u m ≤ T \frac{T}{2} < sum\leq T 2T<sum≤T,第二种是 s u m ≤ T 2 sum\leq \frac{T}{2} sum≤2T。
如果是第一种,那么模完后的结果为 T - sum
,结果一定小于
T
2
\frac{T}{2}
2T;
如果是第二种,那么模完后的结果也显然小于 T 2 \frac{T}{2} 2T。
所以,这里的时间复杂度其实是 O ( n l o g T ) \mathcal{O}(n\ log\ T) O(n log T) 的,最大计算次数为 2 × 1 0 5 × 60 = 1.2 × 1 0 7 2\times 10^5\times 60 = 1.2\times 10^7 2×105×60=1.2×107,可以通过。