Nebius Welcome Round (Div. 1 + Div. 2)(A~D)

A. Lame King

给出一张大小为201 * 201的图,问从(0, 0)到(a, b)最少需要多少步,每一步可以选择上下左右和不走,相连的两步不能向同一个方向。

思路:很显然,两数绝对值相差在1之内就可以直接相加;否则,对于多出来的部分,可以一走一停到达。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 1e5 + 5;
int t, a, b;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> t;
    while(t --) {
        std::cin >> a >> b;
        a = std::max(a, -a);
        b = std::max(b, -b);
        if(abs(a - b) <= 1) {
            std::cout << a + b << '\n';
            continue;
        }
        int max = std::max(a, b);
        int min = std::min(a, b);
        int ans = 2 * min + 1;
        max -= min + 1;
        ans += max * 2;
        std::cout << ans << '\n';
    }
    return 0;
}

B. Vaccination

一个疫苗袋子里有k支疫苗,一个患者最多等w时间,疫苗开封后最多能用d时间,有n个患者。给出患者来的时间,假设防疫站有足够的工作人员进行任何数量的操作,求最少需要开封多少袋疫苗。

思路:为了尽可能减少疫苗开袋,对于时间来的前后的患者,可以让他们等待不超过w时间,使得前后的患者可以使用同一袋疫苗。模拟这个过程即可。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 2e5 + 5;
ll t, n, k, d, w;
ll a[N];

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> t;
    while(t --) {
        std::cin >> n >> k >> d >> w;
        for(int i = 1; i <= n; i ++) {
            std::cin >> a[i];
        }
        int st = a[1], cnt = k - 1, ans = 1;
        bool flag = false;
        for(int i = 2; i <= n; i ++) {
            if(a[i] - st > d && cnt) {
                if(st + d + w >= a[i] && !flag) {
                    st += w;
                    flag = true;
                    cnt --;
                }
                else
                    ans ++, st = a[i], cnt = k - 1, flag = false;
            }
            else if(!cnt)
                ans ++, st = a[i], cnt = k - 1, flag = false;
            else
                cnt --;
        }
        std::cout << ans << '\n';
    }
    return 0;
}

C. Pull Your Luck

给出n个盘块,编号0~n -1,第0号与n - 1号相连。现在位于编号为x的位置,选择1~p的一个数,使得扇区转动(1 + k) * k / 2块,计算能否通过一次旋转使得盘块停留在0号位置。

思路:很容易想到在p这么大的范围内一定有对n取模相等的数。设转动的数字为k,那最后要判断的就是对于任意一个k,((1 + k) * k / 2 % n + x) % n是否等于0。所以主要决定作用来自于这个求等差数列和的位置,而对于1~2*n位置的和,(1 + 2 * n) * n是n的倍数,继续向后的2 * n + 1而言,会重复前面的求和对n取余的余数,所以将问题转化为在1~min(2 * n, p)内找到这个满足条件的数字,降低了时间复杂度,能过。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 2e5 + 5;
ll t, n, x, p;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> t;
    while(t --) {
        std::cin >> n >> x >> p;
        bool flag = false;
        ll res;
        for(ll i = 1; i <= std::min(2 * n, p); i ++) {
            res = (((1 + i) * i / 2) % n + x % n) % n;
            if(res == 0) {
                flag = true;
                break;
            }
        }
        std::cout << (flag ? "Yes" : "No") << '\n';
    }
    return 0;
}

D. Accommodation

对于一层楼上,一共有m盏灯,有一盏灯的屋子m / 2间和两盏灯的屋子m / 4间,给出每一层楼灯的明灭情况,现在不知每一层楼两种屋子的分布情况,求有亮灯的屋子最少和最多有多少间。

思路:对于最少的时候,就是尽可能使两盏灯的屋子中两盏灯全亮;对于最多的时候,就是尽可能使得每一盏灯都分到一个屋子。对于最少的情况,比较容易实现;最多的情况,我们可以反向考虑,计算有多少间两盏灯的屋子两盏灯必须都亮,那用灯的数量减去这些数量就是亮灯房间的个数。

AC Code:

#include <bits/stdc++.h>

typedef long long ll;
#define int long long
const int N = 2e5 + 5;
int n, m;
std::string s;

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> n >> m;
    int max = 0, min = 0;
    while(n --) {
        std::cin >> s;
        s = ' ' + s;
        int cnt = 0;
        int cnt1 = std::count(s.begin(), s.end(), '1');
        for(int i = 1; i <= m; i ++) {
            if(s[i] == '0') continue;
            if(i < m && s[i + 1] == '1')
                cnt ++, i ++;
        }
        min += cnt1 - std::min(m / 4, cnt);
        cnt = 0;
        for(int i = 1; i <= m; i ++) {
            if(i < m && (s[i] != s[i + 1] || s[i] == '0'))
                cnt ++, i ++;
        }
        if(cnt <= m / 4)
            max += cnt1 - (m / 4 - cnt);
        else
            max += cnt1;
    }
    std::cout << min << ' ' << max << '\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值