牛客IOI周赛20-普及组题解

菜鸡第一次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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值