Loading

Codeforces Round 921 (Div. 2)




A - We Got Everything Covered!

难度: ⭐

题目大意

给定n和k两个整数, 要求用前k个小写字母组成一个字符串; 该字符串的子串应包含所有由前k个字母组成的长度为n的字符串全排列; 要求输出最短的满足条件的字符串;

解题思路

这题题目挺唬人, 但其实是个水题; 所谓最短, 其实就是把前k个小写字母重复输出n遍就是最短情况了;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 1e6 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m;
signed main() {
    int t;
    cin >> t;
    while(t--){
        cin >> n >> m;
        for(int i = 1; i <= n; i++){
            for(int j = 0; j < m; j++){
                cout << (char)('a' + j);
            }
        }
        cout << endl;
    }
    return 0;
}




B - A Balanced Problemset?

难度: ⭐⭐

题目大意

给定两个整数n和m; 要求把n分为m份, 所得的分数就是这m个数的最大公约数; 请问该分数最大是多少

解题思路

设最大分数是x, 我们可以先分出m份x, 然后把剩下的全放在其中一份上, 并且剩下的部分(n - m * x)也一定是x的倍数(包括0); 这样就把n分为了两部分: m * x和 a * x; 其中a * x就是(n - m * x); 既然要x尽可能大, 也就是让(m + a)尽可能小, 而且(m + a)和x都是n的因数; 所以只要找出第一个大于等于m的因数就可以了;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 1e6 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m;
signed main() {
    int t;
    cin >> t;
    while(t--){
        cin >> n >> m;
        int minn = n;
        for(int i = 1; i <= n / i; i++){
            if(n % i == 0){
                if(i >= m) minn = min(minn, i);
                if(n / i >= m) minn = min(minn, n / i);
            }
        }
        cout << n / minn << endl;
    }
    return 0;
}




C - Did We Get Everything Covered?

难度: ⭐⭐⭐

题目大意

和A题相似, 不过这次是给出由前k个字母组成的字符串s, 请问他是否包含所有由前k个字母组成的长度为n的子串; 如果没有则输出任意未包含的字符串;

解题思路

从A题找到的规律就是如果要s满足条件, 那么s就要可以被分成n份, 每份都至少含有前k个字母; 所以我们可以根据这个规律扫一遍字符串s, 看看能不能找出n份; 如果不能, 设我们只找到了m份, 那么就取这m份格子最后一个字母, 再加上当前这份缺的那个字母, 然后用'a'补齐字符串长度, 所得到的就是一个缺失的字符串; 这里读者可以思考一下为什么要取每份的最后一个字母;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 1e6 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m;
signed main() {
    int t;
    cin >> t;
    while(t--){
        int k;
        cin >> n >> k >> m;
        string s, res = "";
        cin >> s;
        set<int> st;
        int idx = 0;
        for(int i = 0; i < s.size(); i++){
            st.insert(s[i]);
            if(st.size() == k){
                res += s[i];
                idx++;
                st.clear();
            }
        }
        if(idx >= n) cout << "YES" << endl;
        else {
            for(int i = 0; i < 26; i++){
                if(!st.count('a' + i)){
                    res += ('a' + i);
                    break;
                }
            }
            while(res.size() < n) res += 'a';
            cout << "NO" << endl << res << endl;
        }
    }
    return 0;
}




D - Good Trip

难度: ⭐⭐⭐⭐

题目大意

学校组织k次短途旅行, 每次旅行老师会选择一对学生; 在n个学生中有m对朋友, 每对都有自己的一个初始友谊值fi; 如果老师选中了一对朋友, 那么这对朋友在往后的旅行中友谊值都会+1; 如果不是朋友则仍是0; 请问老师选中的这k对学生的友谊值的和的期望是多少;

解题思路

题意比较难理解; 这题从网上看到一个很妙的题解; 选择一对学生的概率是p = 2 / (n * (n - 1)), 当前所有同学之间友谊值的总和是sum = $\Sigma$ fi; 那么每次选择时, 老师所抽到的学生之间的友谊值期望就是: p * sum; 抽完后友谊值总和增加的概率(抽到朋友时)是: p * m;
所以在k轮抽取中, 每轮答案res都要加上p * sum, 而sum都要更新为sum + 1 * (p * m);
确实很符合逻辑, 但也确实很难想到;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define endl '\n'
using namespace std;
const int N = 1e6 + 10, mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, m;
int qmi(int a, int b){
    int res = 1;
    while(b){
        if(b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}
signed main() {
    int t;
    cin >> t;
    while(t--){
        int k;
        cin >> n >> m >> k;
        int sum = 0, res = 0;
        for(int i = 1; i <= m; i++){
            int a, b, c;
            cin >> a >> b >> c;
            sum = (sum + c) % mod;
        }
        int p = 2 * qmi(n * (n - 1) % mod, mod - 2) % mod;
        for(int i = 1; i <= k; i++){
            res = (res + p * sum % mod) % mod;
            sum = (sum + p * m % mod) % mod;
        }
        cout << res << endl;
    }
    return 0;
}
posted @ 2024-01-29 12:17  mostimali  阅读(24)  评论(0编辑  收藏  举报