Codeforces Round 925 (Div. 3)

在这里插入图片描述

Codeforces Round 925 (Div. 3)

Codeforces Round 925 (Div. 3)

A. Recovering a Small String

题意:给出一个整数n,为三个26个字母的位置序号的和,输出字典序最小的三个字符的字符串。

思路:直接倒推,顺一遍,后面的字母尽可能大。

AC code:

void solve() {
    cin >> n;
    string s = "";
    if (n > 27) {
        n -= 26;
        s += 'z';
        if (n > 26) {
            s += 'z';
            n -= 26;
            s += char('a' + n - 1);
        } else {
            s += char('a' + n - 1 - 1);
            s += 'a';
        }
    }else {
        s += 'a';
        s += 'a';
        n -= 2;
        s += char('a' + n - 2 + 1);
        cout << s << endl;
        return;
    }
    reverse(s.begin(),s.end());
    cout << s << endl;
}

B. Make Equal

题意:n杯水,首先一定能平分,前面的水可以往后匀,是否可以通过这种方式使得n杯水平分。

思路:贪心,从前往后捋,高出平均值记录一下,少了就去些。

AC code:

void solve() {
    cin >> n;
    vector<int> a(n, 0);
    int mx = 0;
    for (int i = 0; i < n; i ++) cin >> a[i], mx += a[i];
 
    int aver = mx / n, now = 0;
    for (int i = 0; i < n; i ++) {
        if (a[i] != aver) {
            if (a[i] >= aver) {
                now += a[i] - aver;
            } else {
                now -= (aver - a[i]);
                if (now < 0) {
                    cout << "NO" << endl;
                    return;
                }
            }
        }
    }
    if (!now) {
        cout << "YES" << endl;
        return;
    }
    cout << "NO" << endl;
}

C. Make Equal Again

题意:通过一次操作,操作为选择任意长度区间变为同一个数,将长度为n的数组a的所有元素相同,最小化区间的元素数量。

思路:注意只能操作一次,那么就仨情况了,前半,后半,中间,记录开头连续相同的数量,和结尾连续相同的数量,取最大,若首尾相等则相加,答案则为除了这些相等的头尾的其余元素。

AC code:

void solve() {
    cin >> n;
    map<int, int> mp;
    for (int i = 1; i <= n; i ++) cin >> a[i], mp[a[i]] ++;
 
    int ans = INF;
    int cnt = 1, cnt2 = 1;
    int l = 1, r = n;
    int st = a[1];
    for (int i = 2; i <= n; i ++) {
        if (a[i] == st) cnt ++;
        else break;
    }
 
    ans = min(ans, n - cnt);
    st = a[n];
    for (int i = n - 1; i >= 1; i --) {
        if (a[i] == st) cnt2 ++;
        else break;
    }
 
    ans = min(ans, n - cnt2);
 
    if (a[1] == a[n]) ans = min(ans, n - cnt - cnt2);
 
    ans = max(0LL, ans);
    cout << ans << endl;
}

D. Divisible Pairs

题意:找出数组中符合条件的元素对,条件为 a i + a j a_i + a_j ai+aj被x整除, a i − a j a_i - a_j aiaj被y整除。

思路:根据条件可以得知:

  • a i − a j a_i - a_j aiaj被y整除即 a i a_i ai % y == 0 && a j a_j aj % y == 0

  • a i + a j a_i + a_j ai+aj被x整除即 ( a i a_i ai%x+ a j a_j aj%x)% x == 0

由以上条件,用map<pair<int, int>, int>来记录每个元素对应xy取模,以第一个条件为基准,定一个元素通过第二个条件找另一个成对元素是否存在,详见代码。

AC code:

void solve() {
    cin >> n >> x >> y;
    for (int i = 1; i <= n; i ++) cin >> a[i];
 
    sort(a+1, a+n+1);
    map<PII, int> mp;
    for (int i = 1; i <= n; i ++) {
        mp[{a[i] % x, a[i] % y}] ++;
    }
    int ans = 0;
    for (int i = 1; i <= n; i ++) {
        int t = (x - (a[i] % x)) % x;
        ans += mp[{t, a[i] % y}];
        if (a[i] % x == t) ans --;
    }
    cout << ans / 2 << endl;
}

E. Anna and the Valentine’s Day Gift

题意:A和B对一个n数组中的元素进行轮流操作,A先手

  • 当A出手时,选择任意一个元素倒转,若倒转后有前置零则消除
  • 当B出手时,选择任意两个不同的元素进行拼接成一个新元素,原序列数量-1

A的获胜条件为最后留下的元素位数小于m,反之B获胜,双方博弈,谁能胜。

思路:

  • 重点只在于一个元素是否有可能通过倒置操作减少位数,即末尾是否有连续的0,且对于一个元素倒置最多减少一次位数

  • 我们可以计算每个元素初始后置0的数量,然后根据这个进行排序

  • 轮到A时则去优先消除后置0多的元素,轮到B则优先可以合并两个元素来保一个后置0

AC code:

int find(int x) {
    int cnt = 0;
    while (x) {
        cnt ++;
        x /= 10;
    }
    return cnt;
}
int find_0(int x) {
    int cnt = 0;
    while (x % 10 == 0 && x != 0) {
        cnt ++;
        x /= 10;
    }
    return cnt;
}
 
void solve() {
    cin >> n >> m;
    vector<PII> a(n);
    for (int i = 0; i < n; i ++) {
        int x; cin >> x;
        a[i].second = x;
        a[i].first = find_0(x);
    }
    sort(a.begin(), a.end());
    int ans = 0;
    for(int i = 0; i < n; i ++) {
        int t = a[i].second;
        ans += find(t);
 
        if (i % 2 != (n - 1) % 2) continue;
        ans -= find_0(t);
    }
    if (ans > m) cout << "Sasha" << endl;
    else cout << "Anna" << endl;
}

F. Chat Screenshots

题意:初始可能会有一个排序序列代表n个用户,用户会发送这个序列,发送的时候把自己调到第一个,即在原序列的基础上,每个用户发送的序列自己都是在第一位的,通过k名用户发送的序列,判断是否可能存在一个初始的序列。

思路:

  • 如果可能存在这样的序列,那么不会存在除当前用户之外的序列顺序出现矛盾的情况。

  • 这里可以直接存图,判断是否是一个拓扑排序即是否不存在环,存在则有矛盾条件。

  • 存图是注意一是不需要存每个用户序列的第一个元素,因为真假存疑,二是除了第一个元素之外序列顺序存,维护前后元素即可。

AC code:

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define db double
#define pb push_back
#define fast() ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
 
typedef long long LL;
typedef pair<char, int> PCI;
typedef pair<int, int> PII;
const int N = 2e5+10, M = 2001;
const int INF = 0x3f3f3f3f3f, mod = 998244353;
int T, n, k;
vector<int> g[N];
int d[N];
 
void solve() {
    for (int i = 1; i <= n; i ++) {
        g[i].clear(), d[i] = 0;
    }
    cin >> n >> k;
    while (k --) {
        vector<int> ca(n);
        for (int i = 0; i < n; i ++) cin >> ca[i];
        for (int i = 1; i < n - 1; i ++) {
            g[ca[i]].pb(ca[i + 1]);
            d[ca[i + 1]] ++;
        }
    }
    queue<int> q;
    for (int i = 1; i <= n; i ++) {
        if (d[i] == 0) q.push(i);
    }
    int cnt = 0;
    while (!q.empty()) {
        auto t = q.front();
        q.pop();
        cnt ++;
        for (auto u : g[t]) {
            d[u] --;
            if (d[u] == 0) q.push(u);
        }
    }
    if (cnt == n) cout << "YES" << endl;
    else cout << "NO" << endl;
}
 
signed main() {
    fast();
    
    T = 1;
    cin >> T;
    while (T --) {
        solve();
    }
    return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值