Educational Codeforces Round 118 (Rated for Div. 2)

A. Long Comparison

题目概述: 比较 x 1 × 1 0 p 1 x1 \times10^{p1} x1×10p1 x 2 × 1 0 p 2 x2 \times10^{p2} x2×10p2 的大小。

思路:
观察数据范围, x x x 最大不超过 1 0 6 10^6 106 ,所以当 p 1 − p 2 > 6 p1 - p2 > 6 p1p2>6 的时候,就可以判定 第一个数大于第二个,相反同理。
如果第一个条件不能判断出,我们让 p 1 , p 2 p1, p2 p1,p2 中较大值(称为 p m p_m pm)减去较小值,较小值为 0 0 0, 此时 p m p_m pm 的值不会超过 1 0 6 10^6 106 可以直接乘到相应的 x x x 上比较大小。
代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;

char solve() {
    ll x1, p1, x2, p2;
    cin >> x1 >> p1;
    cin >> x2 >> p2;
    ll t = min(p1, p2);
    p1 -= t;
    p2 -= t;

    if(p1 > 6) return '>';
    else if(p2 > 6) return '<';
    
    while(p1 --) x1 *= 10;
    while(p2 --) x2 *= 10;

    if(x1 > x2) return '>';
    else if(x1 < x2) return '<';
    else return '=';
}
 
int main() {
   ios::sync_with_stdio(false); 
   cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
   freopen("D:/Cpp/program/Test.in", "r", stdin);
   freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
    int t;
    cin >> t;
    while(t --) 
        cout << solve() << '\n';
}

B. Absent Remainder

题目概述:
一个长度为 n n n 的数组 a a a, 现在要求在数组中找到 ⌊ n 2 n\over2 2n⌋ 对 ( x , y ) (x, y) (x,y), 满足 x x x m o d mod mod y y y 没有在数组 a a a 中出现过。

思路:
两个数相模得到的数一定会小于这两个数,所以直接选数组中任意 ⌊ n 2 n\over2 2n⌋ 对非最小数与 数组中最小的数即可。
代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
int n, a[N];

void solve() {
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> a[i];

    sort(a + 1, a + n + 1);
    int temp = n / 2;
    for(int i = temp; i != 0; i --) {
        cout << a[i + 1] << ' ' << a[1] << '\n';
    }
}

int main() {
   ios::sync_with_stdio(false); 
   cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
   freopen("D:/Cpp/program/Test.in", "r", stdin);
   freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
    int t;
    cin >>t;
    while(t --) {
        solve();
    }
}

C. Poisoned Dagger

题目概述:
一个人攻击一次龙,龙会中毒 k k k 秒,每次攻击会刷新中毒时间,现在给出每次进行攻击的时间和龙的总血量 h h h, 求保证能杀死龙的情况下最小的 k k k
思路:
对龙在一段时间内造成的伤害为 k k k 和两次攻击时间直接的间隔的最小值,用这个性质去二分答案即可。
代码:
cpp

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
const int N = 110; 
ll n, h;
ll a[N];

bool check(ll m) {
    ll res = 0;
    for(int i = 1; i < n; i ++) {
        res += min(a[i + 1] - a[i], m);
        if(res >= h) break;
    }
    res += m;
    return res >= h;
}

void solve() {
    cin >> n >> h;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    ll l = 0, r = h;
    while(l < r) {
        ll mid = l + r >> 1;
        if(check(mid)) r = mid;
        else l = mid + 1;
    }
    cout << l << '\n';
}

int main() {
   ios::sync_with_stdio(false); 
   cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
   freopen("D:/Cpp/program/Test.in", "r", stdin);
   freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
    int t;
    cin >> t;
    while(t --) 
        solve();
    return 0;
}

E. Crazy Robot

题目概述:
L L L 是需要到达的地方 ‘ . . .’ 是 可走的, ‘#’ 是不可走的,现在给机器人下达命令,机器人会按照不是命令所指的方向前进,问哪些点在我们下达命令后机器人可以被 ‘赶’ 到 L L L

思路:
要使得下达命令后机器人会到达实验室,这个格子到 L L L 的路径上的每一个格子都应当满足:

  1. 有一个方向是可以前往 L L L
  2. 除了上面的方向至多再可以有一个方向可以走。

所以我们考虑从 L L L 出发,寻找一条满足出度 ≤ 1 \le 1 1 的路径。

先预处理出所有点的出度,然后从 L L L 开始遍历,找到一个点就使得度减小 1 1 1 , 度小于等于 1 1 1 时就说明该点满足并从该点继续开始更新。简单的来说就是跑一个拓扑排序。
本题数据不足以开二位数组,所以需要一维二维相互转换: n o d e = x ∗ ( m ) + y node = x * (m) + y node=x(m)+y ( m m m 为网格列数)

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e6 + 10;
const pair<int, int> moves[] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
int n, m;

void solve() {
    cin >> n >> m;
    vector<string> s(n);
    PII start;
    for(int i = 0; i < n; i ++) cin >> s[i];

	//预处理出所有点的度
    vector<int> dir(n * m);
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < m; j ++)
            if(s[i][j] == '.') {
                for(auto [dx, dy] : moves) {
                    int x = i + dx, y = j + dy;
                    if(x < 0 || x >= n || y < 0 || y >= m || s[x][y] == '#') continue;
                    dir[i * m + j] ++;
                }
            } else if(s[i][j] == 'L') start = {i, j};

    queue<PII> q;
    q.emplace(start.first, start.second);
    int star = start.first * m + start.second;
    dir[star] = -1;
    while(q.size()) {
        auto t = q.front();
        q.pop();
        int x = t.first, y = t.second;

        if(x * m + y != star) {
            s[x][y] = '+';
        }

        for(auto [dx, dy] : moves) {
            int a = x + dx, b = y + dy;
            if(a < 0 || a >= n || b < 0 || b >= m) continue;
            if(s[a][b] == '#' || dir[a * m + b] == -1) continue;
            dir[a * m + b] --;
            if(dir[a * m + b] <= 1) { //能去的其他方向数量小于等于 1 时候就说明该点满足
                dir[a * m + b] = -1;
                q.emplace(a, b);
            }
        }
    }
    
    for(int i = 0; i < n; i ++) cout << s[i] << '\n';
}

int main() {
   ios::sync_with_stdio(false); 
   cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
   freopen("D:/Cpp/program/Test.in", "r", stdin);
   freopen("D:/Cpp/program/Test.out", "w", stdout);
#endif
    int t;
    cin >> t;
    while(t --) {
        solve();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值