2024牛客寒假算法基础训练营3

本文解析了牛客竞赛中四个算法题目,包括字符串判断、数字手串游戏策略、数组操作、比较函数和特殊数据结构问题,展示了如何通过分析和编写代码解决这些基础和进阶的编程挑战。
摘要由CSDN通过智能技术生成

牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

注:本题解只涉及赛时思路和赛后补题收获,人菜佬勿喷

赛时四题【ABDL】补题【GHMJ】

A.智乃与瞩目狸猫、幸运水母、月宫龙虾

A-智乃与瞩目狸猫、幸运水母、月宫龙虾_2024牛客寒假算法基础集训营3 (nowcoder.com)

在不考虑单词词性的前提下,只要求两个单词的首字母忽略大小写相同时就认为它们可能是一组ubuntu代号,请你编写程序判断给定的两个单词是否可能是一个ubuntu代号。

分析:

签到题,只需判断首字母是否相同即可

代码:

void solve(){
    string s, t;
    cin >> s >> t;
    s[0] = toupper(s[0]);
    t[0] = toupper(t[0]);
    if(s[0] == t[0])
        cout << "Yes\n";
    else
        cout << "No\n";
}

B.智乃的数字手串

B-智乃的数字手串_2024牛客寒假算法基础集训营3 (nowcoder.com)

智乃有一个数字手串,数字手串上有 N 个数字,第 N 个数字与第 1 个数字相邻。智乃决定和清楚姐姐玩一个游戏。

两个人轮流从数字手串上进行取数和交换的操作,当且仅当某两个相邻数字的和为偶数时,可以拿走这两个相邻数字中的任意一个,取数后将剩下的数字按照它们之前的相对顺序重新紧凑排列并选择两个数字交换他们的值,例如一开始的数字环为 [1,3,2,5,4,7] ,取走数字 3 后,数字手串变为 [1,2,5,4,7] ,接下来还可以选择两个数字交换他们的值,例如交换 1 和 2 变为 [2,1,5,4,7] 。(玩家在交换这个环节也可以选择跳过不进行任何交换操作)。

若数字手串的尺寸为 1 ,则玩家可以直接取走最后一个数字并获得游戏的胜利。

若玩家不能进行取数操作,则该玩家失败输掉游戏。

现在清楚姐姐先手取数,若两个人都采取最优策略,谁将获胜?

分析:

读题可以发现胜负是跟可操作次数和总数 N 有关的,只要可操作次数与总数奇偶性不相同那么qcjj就会获胜

代码:

void solve(){
    int n;
    cin >> n;
    vector<int>a(n + 1);
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    ll cnt = 0;
    for(int i = 2; i <= n; i++){
        if(a[i] % 2 != a[i - 1] % 2)
            cnt++;
    }
    if(a[1] % 2 != a[n] % 2)
        cnt++;
    if(cnt % 2 != n % 2)
        cout << "qcjj\n";
    else
        cout << "zn\n";
}

D.chino's bubble sort and maximum subarray sum(easy version)

D-chino's bubble sort and maximum subarray sum(easy version)_2024牛客寒假算法基础集训营3 (nowcoder.com)

分析:

这个题数据范围很小,直接暴力遍历每个交换的位置,然后维护最大子段和即可

代码:

void solve(){
    ll n, k;
    cin >> n >> k;
    vector<ll>a(n + 1);
    for(int i = 1; i <= n; i++){
        cin >> a[i];
    }
    ll ans = (ll)-1e16, sum = 0;
    ll dp[1005] = {0};
    if(k > 0){
        for(int i = 1; i < n; i++){
            swap(a[i], a[i + 1]);
            for(int j = 1; j <= n; j++){
                dp[j] = max(dp[j - 1] + a[j], a[j]);
                ans = ans > dp[j] ? ans : dp[j]; 
            }
            swap(a[i], a[i + 1]);
        }
    }
    else{
        sum = 0;
        for(int j = 1; j <= n; j++){
                dp[j] = max(dp[j - 1] + a[j], a[j]);
                ans = ans > dp[j] ? ans : dp[j]; 
        }
    }
    cout << ans << endl;
}

L.智乃的36倍数(easy version)

L-智乃的36倍数(easy version)_2024牛客寒假算法基础集训营3 (nowcoder.com)

分析:

本题数据范围很小,直接根据题意暴力统计即可通过

代码:

void solve(){
    int n;
    cin >> n;
    vector<int>a(n + 1);
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    int ans = 0;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++){
            if(i == j)
                continue;
            int o = a[i], p = a[j];
            int sum = 0;
            while(p){
                sum++;
                p /= 10;
            }
            if((sum * 10 * o + a[j]) % 36 == 0)
                ans++;
        }
    cout << ans;
}

G.智乃的比较函数(easy version)

G-智乃的比较函数(easy version)_2024牛客寒假算法基础集训营3 (nowcoder.com)

分析:

这个题是easy版本,数据范围也很小,直接分类讨论N为1和2时的情况即可

赛时用的循环n次map记录cmp但是死活过不去,试了好多特例都是对的...

代码:

void solve(){
    int n;
    cin >> n;
    int ok = 1;
    int x, y, z, a, b, c;
    if(n == 1){
        cin >> x >> y >> z;
        if(x == y && z == 1)
            cout << "No\n";
        else
            cout << "YES\n";
    }
    else{
        cin >> x >> y >> z >> a >> b >> c;
        if(x == a && y == b && z != c){
            cout << "No\n";
            return;
        }
        else if(x == y && z == 1 || a == b && c == 1){
            cout << "NO\n";
            return;
        }
        else if(x == b && y == a && z == c && z == 1){
            cout << "NO\n";
            return;
        }
        cout << "YES\n";
    }
}

H.智乃的比较函数(normal version)

H-智乃的比较函数(normal version)_2024牛客寒假算法基础集训营3 (nowcoder.com)

分析:

这个题与easy版本的区别是N的范围不同,但是产生矛盾的逻辑是一样的,所以只需要每种情况都验证即可

代码:

int a[4][4][2];
void solve(){
    int n;
    cin >> n;
    for (int i = 1; i <= 3; i++)
        for (int j = 1; j <= 3; j++)
            for (int k = 0; k < 2; k++) 
                a[i][j][k] = 0;
    for (int i = 0; i < n; i++) {
        int x, y, z; 
        cin >> x >> y >> z;
        a[x][y][z] = 1;
    }
    for (int i = 1; i <= 3; i++)
        if (a[i][i][1]) {
            cout << "NO\n";
            return;
        }
    for (int i = 1; i <= 3; i++)
        for (int j = 1; j <= 3; j++)
            if (a[i][j][1] && a[i][j][0]){
                cout << "NO\n";
                return;
            }
    for (int i = 1; i <= 3; i ++)
        for (int j = i + 1; j <= 3; j++)
            if (a[i][j][1] && a[j][i][1]){
                cout << "No\n";
                return;
            }
    int b[3] = {1, 2, 3};
    do{
        int x = b[0], y = b[1], z = b[2];
        if (a[x][y][1] && a[y][z][1] && a[z][x][1]){
            cout << "No\n";
            return;
        }
        if (a[x][y][1] && a[y][z][1] && a[x][z][0]){
            cout << "No\n";
            return;
        }
        if (a[x][y][0] && a[y][z][0] && a[x][z][1]){
            cout << "No\n";
            return;
        }
    } while (next_permutation(b, b + 3));
    cout << "Yes\n";
}

M智乃的36倍数(normal version)

M-智乃的36倍数(normal version)_2024牛客寒假算法基础集训营3 (nowcoder.com)

分析:

与easy版本的不同在于数据范围。根据取余公式(a+b)mod p = (a % p + b % p) % p

因此只需存一下 a_i%36 和位数,然后暴力统计即可,因为a_i 最大为19位,不会超时

代码:

void solve(){
    ll n;
    cin >> n;
    vector<ll>a(n + 1);
    map<ll, ll>mp;
    ll sum = 0;
    for(ll i = 1; i <= n; i++){
        cin >> a[i];
        mp[a[i] % 36]++;
    }
    for(ll i = 1; i <= n; i++){
        ll num = a[i] % 36;
        ll len = to_string(a[i]).size();
        for (ll j = 0; j < 36; j++) {
             ll t = j;
             for (ll k = 0; k < len; k++) 
                 (t *= 10) %= 36;
             if ((t + num) % 36 == 0)
                 sum += max(mp[j] - (j == num), 0LL);
         }
    }
    cout << sum << endl;
}

J.智乃的相亲活动

J-智乃的相亲活动_2024牛客寒假算法基础集训营3 (nowcoder.com)

分析:

读完题发现只需要保存一下双向的好感,然后直接模拟求好感度即可

代码:

void solve(){
    int n, m, k;
    cin >> n >> m >> k;
    vector<vector<int>>a(n + 1), b(m + 1);
    while(k--){
        int u, v;
        cin >> u >> v;
        a[u].push_back(v);
        b[v].push_back(u);
    }
    db an = 0, bn = 0;
    for(int i = 1; i <= n; i++){
        db num = 1;//db 是double
        for(int j = 0; j < a[i].size(); j++)
            num *= (1 - 1.0 / b[a[i][j]].size());
        an += 1 - num;
    }
    for(int i = 1; i <= m; i++){
        db num = 1;
        for(int j = 0; j < b[i].size(); j++)
            num *= (1 - 1.0 / a[b[i][j]].size());
        bn += 1 - num;
    }
    printf("float\n%.12lf %.12lf\n", an, bn);
}

K.智乃的“黑红树”

K-智乃的“黑红树”_2024牛客寒假算法基础集训营3 (nowcoder.com)

分析:

赛时没看这个题,赛后补题发现这个题还是不难的,先特判不存在的情况:红色节点个数为奇数或者黑色节点个数为偶数或者一个节点的个数大于另一个节点的个数的两倍,然后再贪心构造即可

代码:

void solve(){
    int a[2];
    cin >> a[0] >> a[1];
    if(--a[0] < 0) {
        cout << "NO\n";
        return;
    }
    if(a[0] & 1 || a[1] & 1){
        cout << "NO\n";
        return;
    }
    if(a[0] > a[1] * 2 || a[1] > (a[0] + 1) * 2){
        cout << "NO\n";
        return;
    }
    vector<pair<int, int>>b{{-2, -2}};
    vector<int>c{0};
    int N = 0;
    for (int i = 0; i <= N; i++) {
        if (a[!c[i]] > 1) {
            b[i] = {N + 1, N + 2};
            c.push_back(!c[i]);
            c.push_back(!c[i]);
            b.push_back({-2, -2});
            b.push_back({-2, -2});
            a[!c[i]] -= 2;
            N += 2;
        } 
        else if (a[!c[i]] > 0) {
            cout << "No\n";
            return;
        }     
    }
    if (a[0] || a[1]) {
        cout << "No\n";
        return;
    }
    cout << "Yes\n";
    for (int i = 0; i <= N; i++) {
        cout << b[i].first + 1 << ' ' << b[i].second + 1 << endl;
    }
}
  • 41
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值