Codeforces Round 952 (Div. 4)

Codeforces Round 952 (Div. 4)

Codeforces Round 952 (Div. 4)
在这里插入图片描述

A. Creating Words

AC code:

void solve() {
    string a, b; cin >> a >> b;
    swap(a[0], b[0]);
    cout << a << ' ' << b << endl;
}

B. Maximum Multiple Sum

AC code:

void solve() {
    int n; cin >> n;
    int mx = 0, ans;
    for (int i = 2; i <= n; i ++) {
        int cnt = 0, ca = i;
        while (ca <= n) {
            cnt += ca;
            ca += i;
        }
        if (cnt >= mx) mx = cnt, ans = i;
    }
    cout << ans << endl;
}

C. Good Prefixes

题意:定义一个好的数组中,存在一个元素等于其余所有元素的和,现在寻找大小为n的数组a中有多少前缀数组是好的;

思路:优先队列存取元素,迭代跑一遍即可;

AC code:

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

    int ans = 0;
    if (a[1] == 0) ans += 1;
    int mx = a[1], cnt = 0;
    priority_queue<int> pq;
    for (int i = 2; i <= n; i ++) {
        if (a[i] > mx) {
            pq.push(mx);
            cnt += mx;
            mx = a[i];
        } else {
            pq.push(a[i]);
            cnt += a[i];
        }
        if (mx == cnt) ans ++;
    }
    cout << ans << endl;
}

D. Manhattan Circle

题意:在n*m的字符网格中,找到曼哈顿圆的圆心;

思路:分别找到字符为’#‘的坐标的最大最小值,横纵坐标相加除二即为圆心坐标;

AC code:

void solve() {
    int n, m; cin >> n >> m;
    char g[n + 1][m + 1];
    int l = 2e9, r = -1, u = 2e9, d = -1;
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            char c; cin >> c;
            if (c == '#') {
                l = min(l, j), r = max(r, j);
                u = min(u, i), d = max(d, i);
            }
        }
    }
    int x, y;
    if (l == r) y = l;
    else y = abs(r + l) / 2;
    if (u == d) x = u;
    else x = abs(d + u) / 2;
    cout << x << ' ' << y << endl;
}

E. Secret Box

题意:有一个已知长宽高为x, y, z的盒子B在一个3D坐标系中,现在有一个体积为k的盒子s,通过自由定义一种s的长宽高,s在B中最多可能有多少种放置方法,s的角坐标一定为整数坐标;

思路:暴力枚举S可能的长宽高即可,假设长宽高为a, b, c, 那么该种可能的答案为(x - a) * (y - b) * (z - c);

AC code :

void solve() {
    int x, y, z, k; cin >> x >> y >> z >> k;
    int ans = 0;
    for (int i = 1; i <= k / i; i ++) {
        if (k % i) continue;
        int ca = k / i;
        for (int j = 1; j <= ca / j; j ++) {
            if (ca % j) continue;
            int t[4];
            t[1] = i, t[2] = j, t[3] = ca / j;
            for (int a = 1; a <= 3; a ++) for (int b = 1; b <= 3; b ++) for (int c = 1; c <= 3; c ++) {
                if (a == b || a == c || b == c) continue;
                if (t[a] > x || t[b] > y || t[c] > z) continue;
                ans = max(ans, (x - t[a] + 1) * (y - t[b] + 1) * (z - t[c] + 1));
            }
        }
    }
    cout << ans << endl;
}

F. Final Boss

题意:打BOSS,BOSS的血量为h,我们有n种攻击方式,每回合可以使用任意次攻击,第 i i i种攻击的伤害为 a i a_i ai,但是会有 c i c_i ci的cd,即在x回合使用后,需要在x+ c i c_i ci回合才能再次使用该攻击;最少需要多少回合可以击败BOSS;

思路:二分回合数,每次计算当前回合数最多能造成的伤害;
注意,二分过程中会爆longlong!!!

AC code:

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define fast() ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;

typedef long long LL;
typedef __int128 ll;
typedef pair<int, int> PII;
const int N = 2e5+10, M = 2001;
const int INF = 0x3f3f3f3f3f, MOD = 998244353;

int h, n;
int a[N], c[N];

bool check(int k) {
    ll cnt = 0;
    for (int i = 0; i < n; i ++) {
        cnt += ll((max(0LL, k - c[i])) / c[i] + ((max(0LL, k - c[i])) % c[i] != 0) + 1) * a[i];
        if (cnt >= (ll)h) return true;
    }
    if (cnt >= h) return true;
    return false;
}

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

    int l = 1, r = 1e14;
    while (l < r) {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    cout << l << endl;
}

signed main() {
    fast();
    
    int T = 1;
    cin >> T;
    while (T --) {
        solve();
    }
    return 0;
}

G. D-Function

题意:假设D(n)为数字n的各个数位之和,在 1 0 l 10^l 10l < n < 1 0 r 10^r 10r中,有多少n满足 D(k*n) = k * D(n);

思路:打表可以发现,要想满足题目条件,k*n的各数位直接一定不能有进位,所以首先k一定小于10;

再就是就是有多少个数与k相乘后无进位,每位独立,直接快速幂计算即可;

AC code:

int qmi(int a, int k, int p) {
    int res = 1;
    while (k) {
        if (k & 1) res = res * a % p;
        a = a * a % p;
        k >>= 1;
    }
    return res;
} 

void solve() {
    int l, r, k; cin >> l >> r >> k;
    int ca = 9 / k + 1;
    int ans = qmi(ca, r, MOD) % MOD - qmi(ca, l, MOD) % MOD;
    cout << (ans + MOD) % MOD << endl;
}

H1. Maximize the Largest Component (Easy Version)

题意:

在n*m的网格中,可以任意将一行或一列变为’#‘,操作后整个图中最大的’#'联通块的大小为多少;

思路:

通过BFS以及一个染色数组来记录初始的每个联通块的大小,以及标记同一联通块;

然后暴力枚举当每行or每列染色时,连接当前行/列的最大联通块大小;

AC code:

int f[5] = {1, 0, -1, 0, 1};

void solve() {
    cin >> n >> m;
    vector<vector<char>> v(n + 1, vector<char>(m + 1));
    vector<vector<int>> col(n + 1, vector<int>(m + 1, -1));
    for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
        cin >> v[i][j];
    }
    int st = 1;
    for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
        if (col[i][j] != -1 || v[i][j] == '.') continue;
        queue<pair<int, int>> q;
        q.push({i, j});
        col[i][j] = st;
        while (!q.empty()) {
            auto [x, y] = q.front();
            q.pop();
            for (int t = 0; t < 4; t ++) {
                int nx = x + f[t], ny = y + f[t + 1];
                if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && col[nx][ny] == -1 && v[nx][ny] == '#') {
                    col[nx][ny] = st;
                    q.push({nx, ny});
                }
            }
        }
        st += 1;
    }

    map<int, int> sum;
    for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
        sum[col[i][j]] ++;
    }
    int ans = 0;
    map<int, int> us;
    for (int i = 1; i <= n; i ++) {
        int cnt = 0;
        us.clear();
        for (int j = 1; j <= m; j ++) {
            if (v[i][j] == '.') cnt ++;
            else {
                if (!us[col[i][j]]) cnt += sum[col[i][j]], us[col[i][j]] += 1;
            }
        }
        if (i > 1) 
        for (int j = 1; j <= m; j ++) {
            if (!us[col[i - 1][j]] && v[i - 1][j] == '#') cnt += sum[col[i - 1][j]], us[col[i - 1][j]] += 1;
        }
        if (i < n) 
        for (int j = 1; j <= m; j ++) {
            if (!us[col[i + 1][j]] && v[i + 1][j] == '#') cnt += sum[col[i + 1][j]], us[col[i + 1][j]] += 1;
        }
        ans = max(ans, cnt);
    }
    for (int j = 1; j <= m; j ++) {
        int cnt = 0;
        us.clear();
        for (int i = 1; i <= n; i ++) {
            if (v[i][j] == '.') cnt ++;
            else {
                if (!us[col[i][j]]) cnt += sum[col[i][j]], us[col[i][j]] += 1;
            }
        }
        if (j > 1) 
        for (int i = 1; i <= n; i ++) {
            if (!us[col[i][j - 1]] && v[i][j - 1] == '#') cnt += sum[col[i][j - 1]], us[col[i][j - 1]] += 1;
        }
        if (j < m) 
        for (int i = 1; i <= n; i ++) {
            if (!us[col[i][j + 1]] && v[i][j + 1] == '#') cnt += sum[col[i][j + 1]], us[col[i][j + 1]] += 1;
        }
        ans = max(ans, cnt);
    }
    cout << ans << endl;
}
  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值