Codeforces Round #842 (Div. 2) A - E

A. Greatest Convex

 思路分析:
 给出一个整数k,得到一个比k小
 代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
void solve(){
    
     // 直接输出减去1的结果即可
    int n;
    cin >> n;
    cout << n - 1 << endl;
}
int main(){
    
    
    int T;
    cin >> T;
    while(T -- ) solve();
}

B. Quick Sort

 思路分析:
在这里插入图片描述
 学习积累:
 因为每次最多能处理k个数字,当最后还有 k 个数字的时候我们需要多处理一次,也就相当于 x / k 向上取整,其实可以通过数学处理变成向下取整方便代码计算
在这里插入图片描述
 代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;

void solve(){
    
    
    int n, k, f = 1, x;
    cin >> n >> k;
    for(int i = 0; i < n; i ++ ){
    
    
        cin >> x;
        if(x == f) f ++; // 按照顺序找到 1 2 3 4 ...合法子序列的长度, 之后长度需要减去1
    }

    // n - (f - 1) + k - 1 = n - f + k
    cout << (n - f + k ) / k << endl;
}


int main(){
    
    
    int T;
    cin >> T;
    while(T -- ) solve();
}

C. Elemental Decompress

 思路分析:
在这里插入图片描述
 代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 2e5 + 10;
int p[N], q[N]; // 存储最后的结果
int cp[N], cq[N]; // 记录 p 和 q 序列当中数字出现的次数
int c[N], n; // 本身的序列

void out(){
    
    
    cout << "YES" << endl;
    for(int i = 0; i < n; i ++ ) cout << p[i] << ' ';
    cout << "\n";
    for(int i = 0; i < n; i ++ ) cout << q[i] << ' ';
    cout << "\n";
}

void solve(){
    
    
    cin >> n;
    vector<pair<int, int>> v(n); // 存放 值 - 位置
    for(int i = 0; i < n; i ++ ){
    
    
        cin >> c[i];
        v[i] = make_pair(c[i], i);
        p[i] = q[i] = 0;
        cp[i + 1] = cq[i + 1] = 0;
    }

    sort(v.rbegin(), v.rend()); // 自大到小排序

    for(int i = 0; i < n; i ++ ){
    
     // 第一次放入 p 和 q 序列
        int a = v[i].first, b = v[i].second;
        if(cp[a] == 0){
    
    
            p[b] = a, cp[a] ++ ;
        }
        else{
    
    
            q[b] = a, cq[a] ++ ;
        }
    }

    int r1 = n, r2 = n; // 第二次补充 p 和 q 序列剩下位置的数字
    for(int i = 0; i < n; i ++ ){
    
    
        int u = v[i].second;
        if(p[u] == 0){
    
    
            while(cp[r1]) r1 --;
            if(r1 > q[u]){
    
     // 是否可以合法放入
                cout << "NO" << endl;
                return ;
            }
            p[u] = r1, cp[r1] ++, r1 --;
        }
        else{
    
    
            while(cq[r2]) r2 --;
            if(r2 > p[u]){
    
    
                cout << "NO" << endl;
                return;
            }
            q[u] = r2, cq[r2] ++, r2 --;
        }
    }

    for(int i = 1; i <= n; i ++ ){
    
     // 判断q序列数字是否都出现一次
        if(cq[i] != 1){
    
    
            cout << "NO" << endl;
            return ;
        }
    }
    out();
}


int main(){
    
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t;
    cin >> t;
    while(t -- ) solve();
}

D. Lucky Permutation

 思路分析:
 交换排序的最小操作步骤
在这里插入图片描述
在这里插入图片描述
 代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

void solve(){
    
    
    int n, cnt = 0; // cnt 所需要的操作步骤
    cin >> n;
    vector<int> v(n + 1), cv(n + 1);
    for(int i = 0; i < n; i ++ ){
    
    
         cin >> v[i], v[i] --;
    }

    int ind = 1;
    for(int i = 0; i < n; i ++ ){
    
     // 找到所有的环,对同一个环标记
        if(cv[v[i]]) continue;
        int j = v[i];
        while(cv[j] == 0){
    
    
            cv[j] = ind;
            j = v[j];
            cnt ++;
        }
        cnt --, ind ++;
    }

    for(int i = 0; i < n - 1; i ++ ){
    
     // 是否存在相邻数字在一个环内
        if(cv[i] == cv[i + 1]){
    
    
            cout << cnt - 1 << endl;
            return ;
        }
    }
    cout << cnt + 1 << endl;
    return ;
}

int main(){
    
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int t;
    cin >> t;
    while(t -- ) solve();
}

E. Partial Sorting

 思路分析:
在这里插入图片描述

 代码:

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 3e6 + 10;
LL fac[N], inv[N], n, mod;
qmi(LL a, LL b, LL mod){
    
    
    LL sum = 1;
    while(b){
    
    
        if(b & 1) sum = sum * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return sum;
}
LL C(LL n, LL k){
    
    
    return fac[n] * inv[k] % mod * inv[n - k] % mod;
}
void init(){
    
     // 预处理阶乘和其对应逆元
    fac[0] = inv[0] = 1;
    for(int i = 1; i <= 3000000; i ++ ){
    
    
        fac[i] = fac[i - 1] * i % mod;
    }
    inv[3000000] = qmi(fac[3000000], mod - 2, mod);
    for(int i = 3000000; i > 0; i -- ){
    
    
        inv[i - 1] = inv[i] * i % mod;
    }
}

int main(){
    
    
    cin >> n >> mod;
    init();
    LL ans[4];

    ans[0] = 1; // 以下计算操作次数 f(p) == 0

    ans[1] = (fac[2 * n] * 2 % mod - fac[n]) % mod; // 以下计算操作次数 f(p) <= 1
    ans[1] = (ans[1] - ans[0] + mod) % mod; // f(p) == 1

    ans[2] = fac[2 * n] * fac[n] % mod * C(2 * n, n) % mod * 2 % mod; // 以下计算操作次数 f(p) <= 2
    LL sum = 0;
    for(int i = 0; i <= n; i ++ ){
    
    
        LL sub = 1;
        sub = sub * C(n, i) % mod * C(n, n - i) % mod * C(2 * n - i, n) % mod;
        sub = sub * fac[n] % mod * fac[n] % mod * fac[n] % mod;
        sum = (sum + sub) % mod;
    }
    ans[2] = ans[2] - sum;
    ans[2] = (ans[2] - ans[0] - ans[1] + mod) % mod;; // f(p) == 2

    ans[3] = fac[3 * n]; // 以下计算操作次数 f(p) <= 3
    ans[3] = (ans[3] - ans[0] - ans[1] - ans[2] + 2 * mod) % mod;; // f(p) == 3

    LL result = (ans[1] + 2 * ans[2] + 3 * ans[3]) % mod;
    cout << result << endl;

}

猜你喜欢

转载自blog.csdn.net/weixin_51566349/article/details/128648975