出题人题解

A题

题意:判断字符串 是否为好字符串,需要满足每个字母的大小写形式要么一起出现要么都不出现,每个字母的条件互相独立。

题解:正常枚举 个小写字母是否都是好字符即可。

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 mod = 1e9 + 7;
void solve() {
    int n; cin >> n;
    string s; cin >> s;
    vector<int> c0(26), c1(26);
    for (auto c : s) {
        if (c >= 'a' && c <= 'z') c0[c - 'a'] = 1;
        else c1[c - 'A'] = 1;
    }
    for (int i = 0; i < 26; i++) {
        if (c0[i] != c1[i]) {
            cout << "NO\n";
            return;
        }
    }
    cout << "YES\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}

B题

题意:对于给定的 个数 ,表示第 个同学的数是否大于(1)/等于(0)/小于(-1)它们原本所有数值的平均数。

题解:首先全 情况,一定是满足的,其次 必须要么出现或者要么不出现,因为假设某个数大于平均数了,如果没有一个小于平均数的数来去平衡这个大于平均数的数的差值,就无法满足平均数的定义。

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 mod = 1e9 + 7;
void solve() {
    int n; cin >> n;
    int sum = 0, sum2 = 0;
    for (int i = 1; i <= n; i++) {
        int x; cin >> x;
        if (x == -1) sum = 1;
        else if (x == 1) sum2 = 1;
    }
    if (sum == sum2) cout << "YES\n";
    else cout << "NO\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}

C题

题意:将区间 内的数分别分到两个集合里面去,集合的 为集合内所有数的 值,需要满足两个集合 的值分别为 和非

题解:

首先特判 的情况,输出答案 ;其次若区间长度小于等于 的,则没有一种情况满足要求,直接输出 -1

现在对于其他情况,我们只需要把奇数放一堆,偶数放一堆,就能得到满足条件的情况,因为相邻奇数的 ,所以一定为 ,而偶数一定都共同拥有一个 的因子,所以如果区间长度为偶数,答案为 ,否则为

时间复杂度:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 mod = 1e9 + 7;
void solve() {
    int q; cin >> q;
    for (int i = 1; i <= q; i++) {
        i64 l, r; cin >> l >> r;
        if (l == r) {
            cout << "-1\n";
            continue;
        }
        if (r - l + 1 == 2) {
            cout << (l == 1 ? 0 : -1) << '\n';
            continue;
        }
        cout << (r - l + 1) % 2 << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}

D题

没想到这道模拟题过的比 题少,验题的时候有群友提醒了,当时想当然了,放到 题去了,感觉可能 交换下会好些。

题意:对于一个数组 ,找出对于所有可能的操作能够得到哪些不同众数。

题解: 枚举所有操作,然后用一个 容器存入每个数字当前操作出现的次数,最后取 容器最后一个元素,即是最大的众数,然后标记一下即可,最后升序输出即可。

另外,这题初始时只需要存入 最多 个数,如果将 个数都存入可能会导致 太大, 掉。

时间复杂度:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 mod = 1e9 + 7;
typedef pair<int, int> pi;
int a[100005], sum[1000005], vis[1000005];
set<pi> s;
void add(int x) {
    if (sum[x] > 0) s.erase({sum[x], x});
    sum[x]++;
    s.insert({sum[x], x});
}
void sub(int x) {
    s.erase({sum[x], x});
    sum[x]--;
    if (sum[x] > 0) s.insert({sum[x], x});
}
void solve() {
    int n; cin >> n;
    
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        sum[a[i]]++;
    }
    for (int i = 1; i <= 1000000; i++) {
        if (sum[i]) s.insert({sum[i], i});
    }
    for (int i = 1; i <= n; i++) {
        sub(a[i]); add(a[i] + 1);
        for (int j = 1; j <= n; j++) {
            if (i == j) continue;
            sub(a[j]); add(a[j] - 1);
            vis[(*s.rbegin()).second] = 1;
            sub(a[j] - 1); add(a[j]);
        }
        sub(a[i] + 1); add(a[i]);
    }
    for (int i = 0; i <= 1000001; i++) {
        if (vis[i]) {
            cout << i << ' ';
        }
    }
    cout << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}

E题

题意:通过多少次操作,可以使得数组 变为全相同数的数组,每次操作是将数组 中所有数减去当前数组 的种类数。

题解:特判下初始时数组中每个数都一样的情况;否则可以发现,只有数组 中所有数变为 才会使得所有数一样,又可以发现,种类数是递减的,最多变化 次,且越小的数越先变为 ,所以我们只需要排序去重一下,然后从小到大依次遍历,将当前数减去之前所减的数值,并且依次更新种类数 ,直到全变为 为止。

时间复杂度:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 mod = 1e9 + 7;
void solve() {
    int n; cin >> n;
    vector<i64> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());
    if (a.size() == 1) {
        cout << "0\n";
        return;
    }
    i64 ans = 0, sum = 0, cnt = 0;
    for (int i = 0; i < a.size(); i++) {
        if (a[i] - sum <= 0) {
            cnt = 1;
            continue;
        }
        i64 m = a.size() - i + cnt;
        a[i] -= sum;
        i64 d = (a[i] + m - 1) / m;
        ans += d;
        sum += d * m;
        cnt = 1;
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}

F题

题解:可以发现我们的 的值只会有 种情况,那么对于每种情况,我们分别处理,而每种情况,我们可以发现如果区间长度一样,那么对应的当前 的出现次数也是一样的,而这部分可以直接组合数求解,如果区间长度为 ,且有 个数比 小, 个数比 大,那么就有当前 出现次数 ,但是我们求的是 ,而这个 可能会爆 ,所以需要对次幂进行欧拉降幂处理,即 ,最后将所有数值乘积取模 即可。

时间复杂度:

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const i64 mod = 1610612741;
const i64 mod_phi = mod - 1;
int add(i64 x, i64 y, i64 p) {
    int ans = (x + y) % p;
    return ans;
}

int qp(i64 a, i64 b, i64 p) {
    int res = 1;
    while (b) {
        if (b & 1) res = 1LL * res * a % p;
        a = a * a % p; b >>= 1;
    }
    return res;
}

int C[6005][6005], fac[6005];
void init() {
    fac[0] = 1;
    for (i64 i = 1; i <= 6001; i++) fac[i] = 1LL * fac[i - 1] * i % mod_phi;
    for (int i = 0; i <= 6001; i++) {
        C[i][0] = C[i][i] = 1;
        for (int j = 1; j < i; j++) {
            C[i][j] = add(C[i - 1][j], C[i - 1][j - 1], mod_phi);
        }
    }
}

void solve() {
    int n; cin >> n;
    int ans = 1;
    for (int i = 1; i <= n; i++) {
        int cnt = 0;
        for (int j = 1; j <= n; j++) {
            int x = i - 1, y = n - i;
            int u = j / 2, v = j - 1 - u;
            int res = 1LL * C[x][u] * C[y][v] % mod_phi * fac[j] % mod_phi * fac[n - j] % mod_phi * (n - j + 1) % mod_phi;
            cnt = add(cnt, res, mod_phi);
        }
        ans = 1LL * ans * qp(i, cnt, mod) % mod;
    }
    cout << ans << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    init();
    // cin >> _;
    while (_--) {
        solve();
    }
    return 0;
}
全部评论
感觉c题的解释有点问题,如果奇数只有1个,偶数只有两个的话,偶数组的gcd就是就2,但奇数组的gcd还是这个奇数(非1),但是这样做还是能过是因为把偶数和奇数放一组,另一个偶数单独一组,连续的两个数一个偶数和一个奇数的gcd肯定是1
1 回复 分享
发布于 06-13 14:17 河北
C题是不是少了数据,应该输出-1 1 1 1 有的人这组数据输出0都通过了
点赞 回复 分享
发布于 06-03 19:23 辽宁
d题原来怎么简单粗暴的吗
点赞 回复 分享
发布于 05-31 23:14 甘肃

相关推荐

不愿透露姓名的神秘牛友
今天 10:39
点赞 评论 收藏
分享
求offer的大角牛:不吃香菜
点赞 评论 收藏
分享
评论
6
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务