菜鸡第一次ak牛客系列赛,虽然说这场比赛蛮水,但毕竟是第一次,挺有纪念价值,因此写篇题解纪念一下(
A.完全数
60分做法:暴力把 (1 ~ n-1) 跑一遍,把所有能被n除尽的数(因子)加起来
100分做法:实际上每次找出一个因子时,就可以通过 n/i 求出另一个因子,这样的话便只需要遍历(1 ~ sqtr(n)-1)就可以了
#include <iostream>
using namespace std;
typedef long long LL;
int main() {
LL n, ans = 0;
scanf("%lld", &n);
for (int i = 1; i < n / i; i++) {
if (n % i == 0) {
ans += i;
if (i != 1)
ans += n / i;
}
}
if (ans == n)
puts("Pure");
else if (ans < n)
puts("Early");
else
puts("Late");
return 0;
}
B.移动撤销
看到题目中的撤销操作就知道是一个经典的栈问题了,每次移动操作相当于压栈,撤销操作相当于出栈。
不过有一个坑点要注意,如果栈中只有一个元素时就不能进行出栈操作
#include <stdio.h>
#include <string.h>
const int N = 1e5 + 5;
struct node{
int a, b;
}stk[N];
char op[N];
int main() {
int n, top = 0;
scanf("%d", &n);
scanf("%s", op);
stk[1] = {0, 0};
top++;
int m = strlen(op);
for (int i = 0; i < m; i++) {
int x = stk[top].a;
int y = stk[top].b;
if (op[i] == 'W') {
top++;
stk[top].a = x;
stk[top].b = y + 1;
}
else if (op[i] == 'A') {
top++;
stk[top].a = x - 1;
stk[top].b = y;
}
else if (op[i] == 'S') {
top++;
stk[top].a = x;
stk[top].b = y - 1;
}
else if (op[i] == 'D') {
top++;
stk[top].a = x + 1;
stk[top].b = y;
}
else if (op[i] == 'Z' && top != 1)
top--;
}
printf("%d %d\n", stk[top].a, stk[top].b);
return 0;
}
C.石头剪刀布
一道简单的贪心,先求出能赢的最大局数,再求出能平的最大局数,因为保证了两人的局数相等,剩下的就肯定是只能输掉的局数,将所有赢局数*2加上平局数即可
(第一次写的时候手残把一个加号写成了减号竟然还得了40分:)
#include <iostream>
using namespace std;
typedef long long LL;
LL a[5], b[5];
int main() {
LL n, ans = 0;
scanf("%lld", &n);
for (int i = 1; i <= 3; i++)
scanf("%lld", &a[i]);
for (int i = 1; i <= 3; i++)
scanf("%lld", &b[i]);
for (int i = 1; i <= 3; i++) {
if (i == 3) {
if (a[3] >= b[1]) {
ans += (b[1] + b[1]);
a[3] -= b[1];
b[1] = 0;
}
else {
ans += (a[3] + a[3]);
b[1] -= a[3];
a[3] = 0;
}
}
else {
if (a[i] >= b[i + 1]) {
ans += (b[i + 1] + b[i + 1]);
a[i] -= b[i + 1];
b[i + 1] = 0;
}
else {
ans += (a[i] + a[i]);
b[i + 1] -= a[i];
a[i] = 0;
}
}
}
for (int i = 1; i <= 3; i++)
if (a[i] && b[i])
ans += min(a[i], b[i]);
printf("%lld\n", ans);
return 0;
}
D.夹缝中求和
50分做法:两层for循环判断两个组合的所有可能,求出满足条件的个数即可
100分做法:先将数组排序,然后从小到大对数组中每一个数二分找该数后面所求满足条件的区间大小
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
int a[N];
int main() {
LL n, x, y, ans = 0;
scanf("%lld%lld%lld", &n, &x, &y);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
sort(a + 1, a + n + 1);
for (int i = 1; i < n; i++) {
int l = lower_bound(a + i + 1, a + n + 1, x - a[i]) - a;
int r = (upper_bound(a + i + 1, a + n + 1, y - a[i]) - a) - 1;
ans += (r - l + 1);
}
printf("%lld\n", ans);
return 0;
}