2023 年 10 月 ZZUACM 实验室招新赛题解

A.数位分解

用字符串输入后倒序输出即可

#include<bits/stdc++.h>
using namespace std;
int main() {
    string s;
    cin >> s;
    int n = s.size();
    for (int i = n - 1; i >= 0; i--) {
        cout << s[i] << " ";
    }
    return 0;
}

B.大小写字母互换

while(~scanf("%c", &c))读入每个字符,判断读入的每个字符的类型,如果是大写字母则加上大小写ASCII码的差值,如果是小写字母则减去大小写ASCII码的差值,其他字符直接输出即可

#include<bits/stdc++.h>
using namespace std;
int main() {
    char c;
    char x = 'a' - 'A';
    while (~scanf("%c", &c)) {
        if (c >= 'a' && c <= 'z') cout << (char)(c - x);
        else if (c >= 'A' && c <= 'Z') cout << (char)(c + x);
        else cout << c;
    }
    return 0;
}

C.八进制转十进制

八进制转十进制的方法为:八进制数从右往左数(从0开始)第 i i i 位上的数字乘 8 i 8^i 8i 的总和
例如 ( 114514 ) 8 = ( 4 × 8 0 + 1 × 8 1 + 5 × 8 2 + 4 × 8 3 + 1 × 8 4 + 1 × 8 5 ) 10 = ( 39244 ) 10 (114514)_8=(4×8^0+1×8^1+5×8^2+4×8^3+1×8^4+1×8^5)_{10}=(39244)_{10} (114514)8=(4×80+1×81+5×82+4×83+1×84+1×85)10=(39244)10
故我们将该数以字符串形式读入,翻转后遍历带入公式即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
    string s;
    cin >> s;
    reverse(s.begin(), s.end());
    int n = s.size();
    int ans = 0;
    for (int i = 0; i < n; i++) {
        ans += ((s[i] - '0') * (int)pow(8, i));
    }
    cout << ans;
    return 0;
}

D.西西务者

按照题意读入 5 n 5n 5n 个数,排序后取中间 3 n 3n 3n 个数加和去平均值即可,本题输入输出数据量较大,使用 cin cout 可能会超时

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[7000000];
signed main() {
    int n;
    scanf("%lld", &n);
    for (int i = 0; i < 5 * n; i++) {
        scanf("%lld", &a[i]);
    }
    sort(a, a + 5 * n);
    int sum = 0;
    for (int i = n; i < 4 * n; i++) {
        sum += a[i];
    }
    double ans = 1.0 * sum / (3 * n);
    printf("%.1lf", ans);
    return 0;
}

E.睡大觉

用前缀和数组记录某个点一共睡了多长时间,然后对于每个 l , r l,r l,r ,分别二分找出从 0 0 0 l l l 、从 0 0 0 r r r 一共睡了多长时间,求二者差值即为 l l l r r r 的睡眠时长
本题会卡 cin cout 请使用 scanf printf

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n;
int sum[200010], a[200010];
int Get(long long x){
    int p = lower_bound(a + 1, a + n + 1, x) - a;
    p--;
    if(p & 1) return sum[p];
    else return x - a[p] + sum[p];
    
}
signed main() {
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (i & 1) sum[i] = sum[i - 1] + a[i] - a[i - 1];
        else sum[i] = sum[i - 1];
    }
    int q;
    scanf("%lld", &q);
    while (q--) {
        int l, r;
        scanf("%lld%lld", &l, &r);
        printf("%lld\n", Get(r) - Get(l));
    }
    return 0;
}

F.zzuacm 欢迎你

直接输出,Python一行秒了

print("hello zzuacm")

G.区间和的和

使用滑动窗口记录相邻的 k k k 个数的和,加到 ans 里以后将滑动窗口最左侧的值减去后加入下一个值,遍历整个数组即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
    int n, k;
    cin >> n >> k;
    vector<int> a(n + 5);
    int ans = 0, tsum = 0;
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        if(i < k) tsum += a[i];
    }
    for (int i = k - 1; i < n; i++) {
        ans += tsum;
        tsum -= a[i - (k - 1)];
        tsum += a[i + 1];
    }
    cout << ans;
    return 0;
}

H.Sum of Maximum Weights

我们先将边按权值排序,这样每次处理的都是当前的最大权值

处理每一条边的时候,由于树,这条边的起点和终点一定不连通,所以我们设置两个组 U U U V V V ,那么 U U U 组中任意成员到 V V V 组中任意成员的最大路径边权必为当前边的权值,设为 e e e,故可以写出 a n s   + = s i z [ u ] × s i z [ v ] × e ans\ += siz[u] × siz[v]×e ans +=siz[u]×siz[v]×e ,然后将二组合并,之后对每条边考虑上述情况后即可得出答案

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6 + 5;
const int M = N * 2;
int a[N], b[N];
int f[N];
int siz[N];
int Get(int u) {
    return u == f[u] ? u : f[u] = Get(f[u]);
}
struct edge {
    int u, v, e;
} e[N];
bool cmp(edge x, edge y) {
    return x.e < y.e;
}
signed main() {
    int n;
    cin >> n;
    for (int i = 1; i < n; i++) {
        scanf("%lld %lld %lld", &e[i].u, &e[i].v, &e[i].e);
    }
    for (int i = 1; i <= n; i++) {
        f[i] = i;
        siz[i] = 1;
    }
    sort(e + 1, e + n, cmp);
    int ans = 0;
    for (int i = 1; i < n; i++) {
        edge t = e[i];
        int u = t.u, v = t.v, e = t.e;
        u = Get(u), v = Get(v);
        if (siz[u] < siz[v]) {
            swap(u, v);
        }
        ans += siz[u] * siz[v] * e;
        f[u] = v;
        siz[v] += siz[u];
    }
    cout << ans << endl;
} 

I.区间偶数和

直接输入,从第 l l l 个数开始判断是否为偶数,如果是偶数直接加入答案,一直判断到 r r r

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n, l, r;
    cin >> n >> l >> r;
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        if (!(x & 1) && i >= l && i <= r) ans += x;
    }
    cout << ans;
    return 0;
}

J.矩阵

长得很像这道题,甚至比他简单一点兴趣的同学可以做一下
n n n 为偶数时,我们不难发现对于矩阵中左上角的的数字(即 i ≤ n / 2 , j ≤ n / 2 i \leq n / 2,j \leq n/2 in/2,jn/2 时) m p [ i ] [ j ] mp[i][j] mp[i][j] 在旋转三次以后对应的位置分别在 m p [ j ] [ n − i + 1 ] , m p [ n − i + 1 ] [ n − j + 1 ] , m p [ n − i + 1 ] [ j ] mp[j][n-i+1],mp[n-i+1][n-j+1],mp[n-i+1][j] mp[j][ni+1],mp[ni+1][nj+1],mp[ni+1][j] 这三个位置,所以我们只需要控制这四个位置的数字相同,将变成相同的数所需要的操作次数加入 ans 即可

n n n 为奇数,则还需要加上行和列中间的两条

#include<bits/stdc++.h>
using namespace std;
#define int long long
char mp[110][110];
signed main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> mp[i][j];
            mp[i][j] = mp[i][j] - '0';
        }
    }
    int ans = 0;
    for (int i = 1; i <= n / 2; i++) {
        for (int j = 1; j <= n / 2; j++) {
            int cnt = mp[i][j] + mp[j][n - i + 1] + mp[n - j + 1][i] + mp[n - i + 1][n - j + 1];
            ans += min(cnt, 4 - cnt);
        }
    }
    if (n & 1) {
        for (int i = 1; i <= (n + 1) / 2; i++) {
            int j = (n + 1) / 2;
            int cnt = mp[i][j] + mp[j][n - i + 1] + mp[n - j + 1][i] + mp[n - i + 1][n - j + 1];
            ans += min(cnt, 4 - cnt);
        }
    }
    cout << ans << endl;
    return 0;
}

K.模拟类问题

开一个二维数组记录两人的关系,若 i i i j j j 相邻,则 f [ i ] [ j ] = 1 f[i][j]=1 f[i][j]=1 ,然后枚举每一对人看他们是否曾经挨着即可

#include<bits/stdc++.h>
using namespace std;
int a[60], f[60][60];
int main() {
    int n, m;
    cin >> n >> m;
    while (m--) {
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        for (int i = 2; i <= n; i++) {
            f[a[i]][a[i - 1]] = f[a[i - 1]][a[i]] = 1;
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            ans += (f[i][j] == 0);
        }
    }
    cout << ans;
    return 0;
}

L.找最大值

定义变量 mx 初始化为 − 1 -1 1 用来记录当前最大值,输入时判断该数是否为奇数,若为奇数就和当前最大值取max即可

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n;
    cin >> n;
    int mx = -1;
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        if (x & 1) mx = max(mx, x);
    }
    cout << mx;
    return 0;
}
  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值