2024SZTU_ACM新生夏令营第四次训练赛题解

难度分布

难度分布
Easy
F
E
B
G
Mid
C
D
防AK # 即比正常的新生hard稍难一点
A

F

题目大意

给你一个字符串,前三个字符需要是‘A’, ‘B’, ‘C’,后面的数字需要在1 ~ 349之间,并且不能等于316。

题目思路

跟着题目走即可,同时要注意不能为0和316。

题目代码

#include<stdio.h>
#include<string.h>

#define N 15
char s[N];

int main(){
    
    scanf("%s", s);

    int date = 0;
    for(int i = 3;i < strlen(s);i ++){
        date = date * 10 + int(s[i] - '0');
    }

    if(s[0] == 'A' && s[1] == 'B' && s[2] == 'C' && date != 316 && date <= 349 && date > 0){
        printf("Yes\n");
    }else{
        printf("No\n");
    }

    return 0;
} 

星✌的题解:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e7 + 10;
const int M = 5e4 + 10;
#define IOS ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)

int main() {
    
    char a, b, c;

    int n, x;
    scanf("%c%c%c%d", &a, &b, &c, &n);

    if (n < 350 && n != 316 && n > 0) printf("Yes");
    else printf("No");

	return 0;
}

E

题目大意

给你一个数,然后让你输出一个相应长度的字符串,当第i个字符,i为三的倍数,这个字符为’x’,否则为‘o’。

题目思路

跟着题目走

题目大意

#include<stdio.h>
#include<string.h>

int main(){
    
    int n;
    scanf("%d", &n);

    for(int i = 1;i <= n;i ++){
        printf("%c", (i % 3 == 0 ? 'x' : 'o'));
    }
    
    return 0;
} 

B

题目大意

在这里插入图片描述

题目思路

一看样例就知道要求的是前面n - 1个数的和的相反数。

题目代码

#include<stdio.h>
#include<string.h>

int main(){
    
    int n;
    scanf("%d", &n);
    
    int ans = 0;
    for(int i = 0;i < n - 1;i ++){
        int x;
        scanf("%d", &x);
        ans += x;
    }

    ans = -ans;

    printf("%d\n", ans);
    
    return 0;
} 

G

题目大意

在这里插入图片描述

题目思路

也是跟着题目走就行。

题目代码

#include<stdio.h>
#include<string.h>

#define N 110
char a[N][N], b[N][N]; 

int main(){
    
    int n;
    scanf("%d", &n);
    
    for(int i = 0;i < n;i ++) scanf("%s", a[i]);
    for(int i = 0;i < n;i ++) scanf("%s", b[i]);

    for(int i = 0;i < n;i ++){
        for(int j = 0;j < n;j ++){
            if(a[i][j] != b[i][j]){
                printf("%d %d\n", i + 1, j + 1);
                return 0;
            }
        }
    }
    
    return 0;
} 

C

题目大意

给你一个字符串,看这个字符串好不好,好的要求是1~最大的字母出现次数中满足该次数的字母的个数要不是0,要不是2,否则这个字符串不好。

题目思路

先遍历一遍字符串,看一下每个字母的出现次数,再遍历一下26个字母来看看,每个出现次数对应的字母的个数,然后不满足条件的No,满足的Yes。

题目代码

#include<stdio.h>
#include<string.h>

#define N 110
char s[N];
int cnt[N] = {0}, ans[N] = {0};

int main(){
    
    scanf("%s", s);
    
    int m = 0;
    for(int i = 0;i < strlen(s);i ++){//看一下每个字母的出现次数
        cnt[s[i] - 'a'] ++;
        m = (m > cnt[s[i] - 'a'] ? m : cnt[s[i]- 'a']);//寻找最大的出现次数
    }

    for(char i = 'a';i <= 'z';i ++){//再遍历一下26个字母来看看,每个出现次数对应的字母的个数
        ans[cnt[i - 'a']] ++;
    }

    for(int i = 1;i <= m;i ++){
        if(ans[i] != 0 && ans[i] != 2){
            printf("No\n");
            return 0;
        }
    }

    printf("Yes\n");
    
    return 0;
} 

D

题目大意

在这里插入图片描述

题目思路

就是匹配子序列,但是要注意一定要按顺序匹配,就比如t为abc,这个时候s必须要先匹配要a,然后才能匹配b,然后如果t的结尾如果是x的话,只需要匹配前面两个,反之要匹配三个。

题目代码

#include<stdio.h>
#include<string.h>

#define N 100010
char s[N], t[4];

int main(){
    
    scanf("%s%s", s, t);

    if(t[2] == 'X'){

        int k = 0;//k为t匹配的下标
        for(int i = 0;i < strlen(s);i ++){
            if(char(s[i] - 'a' + 'A') == t[k]){
                k ++;//匹配到前面的,开始加一匹配下一个
            }
        }

        if(k >= 2){//前两个匹配成功此时k为2,所以k至少是2
            printf("Yes\n");
        }else{
            printf("No\n");
        }

    }else{

        int k = 0;
        for(int i = 0;i < strlen(s);i ++){
            if(char(s[i] - 'a' + 'A') == t[k]){
                k ++;
            }
        }

        if(k >= 3){3个匹配成功此时k为3,所以k至少是3
            printf("Yes\n");
        }else{
            printf("No\n");
        }
    }
    
    return 0;
} 

A

题目大意

在这里插入图片描述
看样例更好理解一点

题目思路

思路一(Hard):
本题思路一前置知识点:数学 + 位运算 + 结构体 + 排序
本题的思路来源是未来我们要学的一种高级算法和高级数据结构 ---- 线段树的原理,学完这个算法之后我们看这道题可能就相对比较简单哦,当然不学也是完全可以做出来的。
我们做题要学会画图,接下来是以第一个样例表示的一张图:
在这里插入图片描述
这是一种自下而上的解决方案, 我们可以从下往上检查线段。从最底层的节点开始,确定两端是否必须选择长度为 2 i的线段。
思路二(Easy):
思路二的话大家也是要看上面内张图来理解,每次我尽可能的来选取大的线段的即可。

题目代码

思路一:

#include<stdio.h>
#include<string.h>

typedef long long ll;
#define N 100

struct node{
    ll l, r;
}ans[N];

bool cmp(node x, node y){
    if(x.l != y.l) return x.l < y.l;
    return x.r < y.r;
}

int main(){
    
    ll L, R;
    scanf("%lld %lld", &L, &R);
    
    ll i = 0;
    int k = 0;
    while(L < R){//可以边看代码边看上面的图来理解
        if((L >> i) & 1){//看L的二进制的第i位是不是1
            ans[k ++] = {L, L + (ll(1) << i)};
            L += (ll(1) << i);
        }
        if((R >> i) & 1){
            ans[k ++] = {R - (ll(1) << i), R}; 
            R -= (ll(1) << i);
        }
        i += 1;
    }

    for(int j = 0;j < k - 1;j ++){//冒泡排序
        for(int z = 0;z < k - 1 - j;z ++){
            if(!cmp(ans[z], ans[z + 1])){
                ll xx = ans[z + 1].l, yy = ans[z + 1].r;
                ans[z + 1].l = ans[z].l, ans[z + 1].r = ans[z].r;
                ans[z].l = xx, ans[z].r = yy;
            }
        }
    }

    printf("%d\n", k);

    for(int i = 0;i < k;i ++){
        printf("%lld %lld\n", ans[i].l, ans[i].r);
    }
    
    return 0;
} 

思路二:
下面的代码本来是要用结构体的,但是赛场上根据蔡泽垲同学的代码进行了修改,在此对蔡泽垲同学提出表扬,当然赛场上能做出这道题的孟晖同学也很棒。

#include<stdio.h>
#include<string.h>
#include<math.h>

typedef long long ll;
#define N 100000

ll ans[N];

int main(){
    
    ll L, R;
    scanf("%lld %lld", &L, &R);
    
    int k = 0;
    while(L < R){
        for(ll i = 60;i >= 0;i --){//尽可能选大的线段
            ll w = ll(pow(2, i));
            if((L + w <= R) && (L % w == 0)){
                ans[k ++] = L;
                ans[k ++] = L + w;
                L += w;
                break;
            }
        }
    }

    printf("%d\n", k / 2);//上一个L + w会和下一个L相等,所以要除2

    for(int i = 0;i < k;i += 2){
        printf("%lld %lld\n", ans[i], ans[i + 1]);
    }
    
    return 0;
} 
  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值