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

难度分布

难度分布
Easy
A
D
B
Mid
C
F
Hard
E
G

A

题目大意

给你两个数, 分别为A和B,输出一个在0和9之间而不等于A + B(A + B <= 9)的数。

题目思路

因为9为奇数,所以我们输出9 -(A + B), 它一定不等于A + B,

题目代码

#include<stdio.h>

typedef long long ll;

int main(){

	int A, B;
	scanf("%d%d", &A, &B);

	printf("%d", 9 - (A + B));

	return 0;
}

D

题目大意

在这里插入图片描述

题目思路

题目怎么说,就怎么做呗

题目代码

#include<stdio.h>

typedef long long ll;

int main(){

	int n, k;
	scanf("%d%d", &n, &k);

	for(int i = 0;i < n;i ++){
		int x;
		scanf("%d", &x);
		if(x % k == 0) printf("%d ", x / k);
	}
	printf("\n");

	return 0;
}

B

题目大意

给你一个二维矩阵,输出每一行值等于1的列坐标

题目思路

题目怎么说,我们就怎么做

题目代码

#include<stdio.h>

typedef long long ll;

int main(){

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

	for(int i = 1;i <= n;i ++){
		for(int j = 1;j <= n;j ++){
			int x;
			scanf("%d", &x);
			if(x == 1) printf("%d ", j);
		}
		printf("\n");
	}

	return 0;
}

F

题目大意

给你一个数n, 求不大于n的最大的即是回文数也是三的幂的数。

题目思路

n最大为1e18,同时因为要是3的幂,所以最大只需要i从1枚举到1e6,每个数的数位最大为63,所以枚举一遍同时判断回文是不可能超时的。

题目代码

#include<stdio.h>

typedef long long ll;

int a[100];

bool check(ll x){//判断是否回文
	int k = 0;
	while(x){
		a[++ k] = (x % 10);
		x /= 10;
	}
	bool ok = true;
	for(int i = 1;i <= k;i ++){
		if(a[i] != a[k - i + 1]){
			ok = false;
			break;
		}
	}

	return ok;
}

int main(){

	ll n;
	scanf("%lld", &n);
    
    ll ans = 0;
	for(ll i = 1;i * i * i <= n;i ++){
		if(check(i * i * i)){
			ans = i * i * i;
		}
	}

	printf("%lld", ans);

	return 0;
}

C

题目大意

在这里插入图片描述

题目思路

如果我们正向扫s的话,每次执行一次,时间复杂度高达o(n^2),会tle,所以我们反向来即可。

题目代码

#include<stdio.h>

typedef long long ll;
#define N 1000100

int a[N], ans[N];
char s[N];

void solve(){
	int n, m;
	scanf("%d%d", &n, &m);

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

	scanf("%s", &s);
    
    int l = 0, r = 0;
	for(int i = 0;i < n;i ++){
		if(s[i] == 'L'){
			r ++;
			l ++;
		}
	}
    
    int mul = 1;
	for(int i = n - 1;i >= 0;i --){
		if(s[i] == 'L'){
			mul = (mul * a[-- l]) % m;
		}else{
			mul = (mul * a[r ++]) % m;
		}
		ans[i] = mul;
	}

	for(int i = 0;i < n;i ++){
		printf("%d ", ans[i]);
	}
	printf("\n");

}

int main(){

	int t;
	scanf("%d", &t);
	while(t --){
		solve();
	}
	
	return 0;
}

G

题目大意

给你n个一对l,r(l <= r)的数,看你是否可以给出一组序列A,使得Li <= Ai <= Ri, 同时序列A所有的数加起来等于0。

题目思路

首先看是否存在一个序列所有的数加起来等于0,直接根据零点定理,最大值大于0, 最小值小于0,函数单调,则中间必然存在零点。
在这里插入图片描述
然后我们构造序列,我们可以先存入最小值,同时观察剩下的最大值可不可以补充这些最小值,然后快不行时就赶紧补充最大值。
在这里插入图片描述

题目代码

#include<stdio.h>

typedef long long ll;
#define N 200010

ll ans[N], l[N], r[N];

int main(){

    int n;
    scanf("%d", &n);
    
    ll lo = 0, hi = 0;
    for(int i = 0;i < n;i ++){
    	scanf("%lld%lld", &l[i], &r[i]);
    	lo += l[i];//最小值
    	hi += r[i];//最大值
    }
    
    int cur = 0;
    if(lo <= 0 && hi >= 0){//零点定理
    	printf("Yes\n");
    	int flag = 1;
    	for(int i = 0;i < n;i ++){
    		if(flag){
    			if(hi - (r[i] - l[i]) <= 0){
    			    //当我们发现剩余最大值补不了l和r的差距时
    				flag = 0;
    				ans[cur ++] = (r[i] - hi);
    				hi = 0;
    			}else{
    				ans[cur ++] = l[i];//先拿最小的
    				hi -= (r[i] - l[i]);
    			}
    		}else{
    			ans[cur ++] = r[i];//然后全拿最大的
    		}
    	}

    	for(int i = 0;i < cur;i ++){
    		printf("%d ", ans[i]);
    	}
    	printf("\n");
    }else{
    	printf("No\n");
    }

	return 0;
}

E

题目大意

在这里插入图片描述

题目思路

逆天神题,只能说不想评价,看代码吧

NOTE:注意scanf %c 会读入换行注意解决

题目代码

#include<stdio.h>

typedef long long ll;
#define N 5

char a[N][N];
int cnt[N];

int main(){

	for(int i = 1;i <= 3;i ++){
		scanf("%s", a[i]);
		for(int j = 3;j >= 1;j --){
			a[i][j] = a[i][j - 1];
		}
		for(int j = 1;j <= 3;j ++){
			if(a[i][j] == '0') cnt[0] ++;
			if(a[i][j] == 'X') cnt[1] ++;
		}
	}

	int ok_X1 = ((a[1][1] == 'X' && a[1][2] == 'X' && a[1][3] == 'X') + (a[2][1] == 'X' && a[2][2] == 'X' && a[2][3] == 'X') + (a[3][1] == 'X' && a[3][2] == 'X' && a[3][3] == 'X'));
	int ok_O1 = ((a[1][1] == '0' && a[1][2] == '0' && a[1][3] == '0') + (a[2][1] == '0' && a[2][2] == '0' && a[2][3] == '0') + (a[3][1] == '0' && a[3][2] == '0' && a[3][3] == '0'));
    int ok_X2 = (a[1][1] == 'X' && a[2][2] == 'X' && a[3][3] == 'X') + (a[1][3] == 'X' && a[2][2] == 'X' && a[3][1] == 'X');
    int ok_O2 = (a[1][1] == '0' && a[2][2] == '0' && a[3][3] == '0') + (a[1][3] == '0' && a[2][2] == '0' && a[3][1] == '0');
    int ok_X3 = ((a[1][1] == 'X' && a[2][1] == 'X' && a[3][1] == 'X') + (a[1][2] == 'X' && a[2][2] == 'X' && a[3][2] == 'X') + (a[1][3] == 'X' && a[2][3] == 'X' && a[3][3] == 'X'));
    int ok_O3 = ((a[1][1] == '0' && a[2][1] == '0' && a[3][1] == '0') + (a[1][2] == '0' && a[2][2] == '0' && a[3][2] == '0') + (a[1][3] == '0' && a[2][3] == '0' && a[3][3] == '0'));
    int ok_O = ok_O1 + ok_O2 + ok_O3;
    int ok_X = ok_X1 + ok_X2 + ok_X3; 


	if(ok_O && ok_X){//不可能同时赢
		printf("illegal\n");
		return 0;
	}

	if(cnt[0] > cnt[1]){//0不可能大于x
		printf("illegal\n");
		return 0;
	}

	if(cnt[1] > cnt[0] + 1){//x走一步0就要走一部
		printf("illegal\n");
		return 0;
	}

	if(ok_O && !ok_X){
		if(ok_O1 > 1 || ok_O3 > 1 || cnt[1] != cnt[0]){//不光有一行赢,同时赢了就不要再下了
			printf("illegal\n");
		}else{
			printf("the second player won\n");
		}
		return 0;
	}

	if(!ok_O && ok_X){
		if(ok_X1 > 1 || ok_X3 > 1 || cnt[1] != cnt[0] + 1){
			printf("illegal\n");
		}else{
			printf("the first player won\n");
		}
		return 0;
	}

	if(cnt[0] + cnt[1] == 9){//平局
		printf("draw\n");
		return 0;
	}

	if(cnt[0] < cnt[1]){
		printf("second\n");
	}else{
		printf("first\n");
	}

	return 0;
}
  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值