whvp 3 - Codeforces Round #761 (Div. 2)

Codeforces Round #761 (Div. 2)

Codeforces Round #761 (Div. 2)

A. Forbidden Subsequence

题意:给出一个串s和一个串t,要求出s字典序最小的排列使得不包含t作为subsequence,其中t为abc的排列

其实就是对abc三个字母进行排列使得不按t给出的顺序,如果t是abc就按acb其他都按abc,即所有字母按字母序给出

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int cnt[30];

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);

    int T;
    cin >> T;
    while (T--) {
        for (int i = 0; i <= 26; ++i) cnt[i] = 0;
        string s, t;
        cin >> s >> t;
        int sz = s.size();
        for (int i = 0; i < sz; ++i) {
            cnt[s[i] - 'a']++;
        }
        if (!cnt[0] || !cnt[1] || !cnt[2]) {
            for (int i = 0; i < 26; ++i) {
                for (int j = 0; j < cnt[i]; ++j) {
                    cout << (char) ('a' + i);
                }
            }
            cout << endl;
            continue;
        }
        for (int i = 0; i < cnt[0]; ++i) cout << 'a';
        if (t == "abc") {
            for (int i = 0; i < cnt[2]; ++i) cout << 'c';
            for (int i = 0; i < cnt[1]; ++i) cout << 'b';
        } else {
            for (int i = 0; i < cnt[1]; ++i) cout << 'b';
            for (int i = 0; i < cnt[2]; ++i) cout << 'c';
        }

        for (int i = 3; i < 26; ++i) {
            for (int j = 0; j < cnt[i]; ++j) {
                cout << (char) ('a' + i);
            }
        }
        cout << endl;
    }
}

B. GCD Problem

题意:给出n,要求三个不同的数abc使得 gcd ⁡ ( a , b ) = c \gcd(a,b) = c gcd(a,b)=c

设c= 1,一定可以找出两个数ab互质

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;


signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);

    ll T;
    cin >> T;
    while (T--) {
        ll n;
        cin >> n;
        n--;
        if (n & 1) {
            cout << 2 << " " << n - 2 << " " << 1 << endl;
            continue;
        }
        if (n % 4 == 0) {
            cout << n / 2 - 1 << " " << n / 2 + 1 << " " << 1 << endl;
        } else cout << n / 2 - 2 << " " << n / 2 + 2 << " " << 1 << endl;
    }
}

C. Paprika and Permutation

题意:给出一个长度为n的数列,每次操作为选一个i,使得 a i = a i m o d    x a_i = a_i \mod x ai=aimodx,其中每次操作的ix都可以重新任选,要求最少的操作使得操作完的数列为1到n的排列,或声明不存在

将在1-n范围中能用的数先去掉,剩下的数从大到小排序,对应要求的1-n也从大到小排序依次去看他能不能操作

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;
vector<int> a, b;
bool vis[N];

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);

    ll T;
    cin >> T;
    while (T--) {
        ll n;
        cin >> n;
        for (int i = 1; i <= n; ++i) vis[i] = 0;
        a.clear(), b.clear();
        for (int i = 1, x; i <= n; ++i) {
            cin >> x;
            if (x <= n && !vis[x]) {
                vis[x] = 1;
            } else {
                a.push_back(x);
            }
        }
        sort(a.begin(), a.end(), [&](int x, int y) { return x > y; });
        for (int i = n; i >= 1; i--) {
            if (!vis[i]) {
                b.push_back(i);
            }
        }

        bool flag = 1;
        int siz = a.size();
        for (int i = 0; i < siz; ++i) {
            if (a[i] <= b[i] * 2){
                flag = 0;
                break;
            }
        }
        if(flag) cout << a.size() << endl;
        else cout << -1 << endl;
    }
}

D1. Too Many Impostors (easy version)

题意:交互题,有n个人(n为3的倍数),其中有k个是骗子,其余为普通人,每次可以任选三个人,回答给出这三个人中是骗子多还是普通人多,2n次询问内给出所有骗子的位置,保证 1 3 < k < 2 3 \frac{1}{3} < k < \frac{2}{3} 31<k<32

相当于n个球,k个白球,剩下为黑球…

如果能找出一个黑球一个白球,接下来只要O(n)询问就可以得出其余球的状况,由于题给n为3的倍数,将每三个划分为一组,依次询问,找出一组黑球多的一组白球多的,(因为k的范围所以一定可以找出这样的两组

只考虑这两组六个球,对于每组的头拿出来,通过对剩余四个位置的综合询问可以得出这两个球的状态,调整找出一黑一白两个球,

这种做法大概是 O ( 4 3 n ) O(\frac{4}{3}n) O(34n)次询问

#include <bits/stdc++.h>

using namespace std;

vector<int> vec;

signed main() {
    int T;
    cin >> T;
    while (T--) {
        vec.clear();
        int n;
        cin >> n;
        int blackpos, whitepos;
        int black;
        for (int i = 1; i <= n; i += 3) {
            cout << "? " << i << " " << i + 1 << " " << i + 2 << endl;
            int x;
            cin >> x;
            if (x == 1) {
                blackpos = i;
            } else {
                whitepos = i;
            }
        }

        int cnt0 = 0, cnt1 = 0;

        vector<int> qe;
        qe.clear();
        qe.push_back(blackpos + 1);
        qe.push_back(blackpos + 2);
        qe.push_back(whitepos + 1);
        qe.push_back(whitepos + 2);

        int sz = qe.size();
        for (int i = 0, x; i < sz; ++i) {
            cout << "? " << blackpos << " " << whitepos << " " << qe[i] << endl;
            cin >> x;
            if (x == 0) {
                cnt0++;
                vec.push_back(qe[i]);
            } else {
                cnt1++;
                black = qe[i];
            }
        }

        if (cnt1 == 4) { // 2black //
            vec.clear();
            whitepos++;
            vec.push_back(whitepos);
            for (int i = 1, x; i <= n; ++i) {
                if (i == blackpos || i == whitepos - 1 || i == whitepos) continue;
                cout << "? " << blackpos << " " << whitepos << " " << i << endl;
                cin >> x;
                if (x == 0) vec.push_back(i);
            }
        } else if (cnt0 == 4) { //2white //
            vec.clear();
            vec.push_back(blackpos);
            vec.push_back(whitepos);
            blackpos++;
            for (int i = 1, x; i <= n; ++i) {
                if (i == blackpos - 1 || i == blackpos || i == whitepos) continue;
                cout << "? " << blackpos << " " << whitepos << " " << i << endl;
                cin >> x;
                if (x == 0) vec.push_back(i);
            }
        } else { //1 black 1white //

            for (int i = 1, x; i <= n; ++i) {
                if ((blackpos <= i && i <= blackpos + 2) || (whitepos <= i && i <= whitepos + 2)) continue;
                cout << "? " << blackpos << " " << whitepos << " " << i << endl;
                cin >> x;
                if (x == 0) vec.push_back(i);
                else black = i;
            }
            cout << "? " << black << " " << vec[vec.size() - 1] << " " << blackpos << endl;
            int x;
            cin >> x;
            if (x == 1) vec.push_back(whitepos);
            else vec.push_back(blackpos);
        }
        cout << "! " << endl;
        int res = vec.size();
        cout << res << " ";
        for (int i = 0; i < res; ++i) {
            cout << vec[i] << " ";
        }
        cout << endl;
    }
}

D2. Too Many Impostors (hard version)

题意与D1一致,询问次数限制变为n+6.

官方题解大概是n+3左右
分组和D1思路一致,这里用 n 3 \frac{n}{3} 3n,取出一个0组一个1组,标号abcdef,分别对abc,bcd,cde,def询问,其中abc/def之前询问过,额外+2次,找出一黑一白
每组用2的代价确定三个的01值
当一个组确定为0组或1组的时候,他的排布一共就只有4种,每次询问减少一半的情况
假设询问0组,标号i,j, k ,用1去配合 问1 i,j,如果01,则k为0,在用01,i询问得出i,推出j;

后排给个n+1的思路:

谢谢@hoshimi同学(嗯嗯嗯对对对,直接cv了,讲得挺清楚的

0组abc,1组def
问abd和abe,如果都是0,说明ab都是0,再问ade和aef,如果00则def101,01则def011,10则def110,然后找个0和1检验c,这样是2组7次
如果abd和abe是01之类的就知道def是什么了,再用其中的1检验abc(和a检验def同理)
然后同理检验别的组

代码先咕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值