前言

虽然这次比赛不限制编程语言,但为了保证大家都能看懂题解中的代码,本次题解使用C语言进行编码。


A 赛博银河编程大作战

CV输出即可,字符串里有双引号可以使用转义字符。

#include <stdio.h>

int main()
{
	printf("I AK the sixth \"Chasing Dreams in Space, Compiling the Future\" Fun Code Programming Competition of the School of Computer Science and Engineering.");
	return 0;
}

B 基建工程

简单的输入输出题,没什么好说的。

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

int main()
{
	int a;
	char b;
	double c;
	scanf("%d %c %lf", &a, &b, &c);
	printf("%d %c %.2lf", abs(a), b - 32, c);
	return 0;
}

C 神秘的礼物盒I

观察题目可知能对答案做出贡献的运算只有加法和乘法,因此一共只有四种情况,枚举这四种情况然后取最大值即可。

#include <stdio.h>

int main()
{
	int a, b, c; scanf("%d %d %d", &a, &b, &c);
	int ans = 0;
	if(a + b + c > ans) ans = a + b + c;
	if(a * b + c > ans) ans = a * b + c;
	if((a + b) * c > ans) ans = (a + b) * c;
	if(a * b * c > ans) ans = a * b * c;
	printf("%d", ans);
	return 0;
}

D 社交的手腕

令我的带出价值为 ,小航的带出价值为

时,此时不用操作就能使我的带出价值 ≥ 小航的带出价值。

反之我们可以选择段 ,使用后使我的带出价值将 ≥ 小航的带出价值。

因此无论情况如何,只需要输出 Yes 就行了。

不知道大家是不是被题面吓到了,过这个题的人意外的少。

#include <stdio.h>

int main()
{
	int t; scanf("%d", &t);
	while(t --) printf("Yes\n");
	return 0;
}

E 神秘的礼物盒Ⅱ

可以发现数据范围变了,增加了负数,因此要判断的情况也变多了。

不过就算这样,总的情况依然不多,直接暴搜就可以了。

还有要记得开 long long ,除法要判断分母不为 0 。

#include <stdio.h>
#define ll long long

ll a[4], ans = -4e18;
ll max(ll a, ll b) {return a > b ? a : b;}
void dfs(ll x, int dep) {
	if(dep == 4) {
		ans = max(ans, x);
		return;
	}
	dfs(x + a[dep], dep + 1);
	dfs(x - a[dep], dep + 1);
	dfs(x * a[dep], dep + 1);
	if(a[dep] != 0) dfs(x / a[dep], dep + 1);
}

int main()
{
	for(int i = 1; i <= 3; ++ i) scanf("%lld", &a[i]);
	dfs(a[1], 2);
	printf("%lld", ans);
	return 0;
}

对于没学过算法设计的同学来说,这显然有些超纲了。那我们不妨换种思路,既然数组中的元素可以通过下标枚举,那操作是否也可以通过数组下标枚举呢?答案是可以的!把操作封装成函数,再使用函数指针就好了。

#include <stdio.h>
#define ll long long

ll add(ll x, ll y) {return x + y;}
ll sub(ll x, ll y) {return x - y;}
ll mul(ll x, ll y) {return x * y;}
ll div(ll x, ll y) {return x / y;}
ll max(ll x, ll y) {return x > y ? x : y;}

ll (* func[])(ll, ll) = {add, sub, mul, div};

int main()
{
	ll a, b, c; scanf("%lld %lld %lld", &a, &b, &c);
	ll ans = -4e18;
	for(int i = 0; i < 4; ++ i) {
		if(b == 0 && i == 3) continue;
		ll x = func[i](a, b);
		for(int j = 0; j < 4; ++ j) {
			if(c == 0 && j == 3) continue;
			ans = max(ans, func[j](x, c));
		}
	}
	printf("%lld", ans);
	return 0;
}

对于只会C语言的同学来说,函数指针确实还是比较难想到,因此这里再提供一种只用到C语言基本语法的解法。

#include <stdio.h>
#define ll long long

ll a[3], b[4]; 
ll max(ll x, ll y) {return x > y ? x : y;}

int main()
{
	scanf("%lld %lld %lld", &a[0], &a[1], &a[2]);
	b[0] = a[0] + a[1];
	b[1] = a[0] - a[1];
	b[2] = a[0] * a[1];
	b[3] = (a[1] != 0 ? a[0] / a[1]: -2e9);
	ll ans = -4e18;
	for(int i = 0; i < 4; ++ i) {
		if(a[1] == 0 && i == 3) continue;
		ans = max(ans, b[i] + a[2]);
		ans = max(ans, b[i] - a[2]);
		ans = max(ans, b[i] * a[2]);
		if(a[2] != 0) ans = max(ans, b[i] / a[2]);
	}
	printf("%lld", ans);
	return 0;
}

可以发现代码其实也没有长多少,不过这题毕竟是简单题,不用写很长的代码也是应该的~


F 提瓦特质数大冒险

这个题主要考循环和素数判断,如果素数判断的时间复杂度大于 会被卡掉。

本来以为这个题过的人会挺多的,没想到那么多人不会翻转数位。

#include <stdio.h>

int main()
{
	int n; scanf("%d", &n);
	while(n --) {
		int x; scanf("%d", &x);
		int y = 0; 
		while(x) {
			y += x % 10, x /= 10;
			if(x) y *= 10;
		}
		int flag = (y > 1);
		for(int i = 2; i <= y / i; i ++) {
			if(y % i == 0) {
				flag = 0;
				break;
			}
		}
		if(flag) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

G 音盒谜题

音盒里的东西非常多,但是只需要交换音盒。因此我们用一个指针数组记录每个音盒的地址,交换时只需交换指针即可。

#include <stdio.h>
#define rep(i, s, e) for(int i = s; i <= e; ++ i)
#define N 100007

int a[11][N];
int *b[10];

int main()
{
	int n, m; scanf("%d %d", &n, &m);
	rep(i, 1, n) rep(j, 1, m) scanf("%d", &a[i][j]);
	rep(i, 1, n) b[i] = a[i];
	int k; scanf("%d", &k);
	while(k --) {
		int x, y; scanf("%d %d", &x, &y);
		int *tmp = b[x];
		b[x] = b[y];
		b[y] = tmp;
	}
	int q; scanf("%d", &q);
	while(q --) {
		int x; scanf("%d", &x);
		rep(i, 1, m) printf("%d ", b[x][i]);
		printf("\n");
	}
	return 0;
}

H 星际货币兑换

首先要判断是否需要再增加货币,需要将所有类型的货币统一换算成最低一级的货币。 之后如果要再增加货币的话,对于每一级货币,需要增加的数量为

#include <stdio.h>
#define ll long long
#define N 15

ll x[N], a[N], b[N], ans[N];
int n;

ll getsum(ll a[]) {
	ll res = a[1];
	for(int i = 2; i <= n; ++ i) res = res * x[i] + a[i];
	return res;
}

int main()
{
	scanf("%d", &n);
	for(int i = 2; i <= n; ++ i) scanf("%lld", &x[i]);
	for(int i = 1; i <= n; ++ i) scanf("%lld", &a[i]);
	for(int i = 1; i <= n; ++ i) scanf("%lld", &b[i]);
	ll have = getsum(a), need = getsum(b);
	if(have >= need) {
		for(int i = 1; i <= n; ++ i) printf("0 ");
	} else {
		ans[n] = need - have;
		ll k = 1;
		for(int i = n - 1; i >= 1; -- i) {
			k *= x[i+1], ans[i] = (need - have + k - 1) / k;
		}
		for(int i = 1; i <= n; ++ i) printf("%lld ", ans[i]);
	}
	return 0;
}

I 指针与心跳的二重奏

模拟题,代码最长的一集,把链表的基本操作考了个遍。细节很多,不建议在这个题上花费太多时间。

#include <stdio.h>
#include <string.h>
#define N 1005

typedef struct Node {
	char addr[10];
	int val;
	int next;
} Node;

Node list[N];
int tot;

int find(char ad[]) {
	int res = 0;
	while(strcmp(list[res].addr, ad) && list[res].next) res = list[res].next;
	return res;
}

void insert(int idx) {
	char ad[10];
	int x; scanf("%s %d", ad, &x);
	list[++ tot].next = list[idx].next;
	list[idx].next = tot;
	for(int i = 0; i < 8; ++ i) list[tot].addr[i] = ad[i];
	list[tot].val = x;
}

void del(char ad[]) {
	int idx = 0;
	while(list[idx].next && strcmp(list[list[idx].next].addr, ad)) idx = list[idx].next;
	if(list[idx].next) list[idx].next = list[list[idx].next].next;
}

void swap(int x, int y) {
	int tmp = list[x].val;
	list[x].val = list[y].val;
	list[y].val = tmp;
	for(int i = 0; i < 8; ++ i) {
		char c = list[x].addr[i];
		list[x].addr[i] = list[y].addr[i];
		list[y].addr[i] = c;
	}
}

int main()
{
	int n; scanf("%d", &n);
	memset(list, 0, sizeof(Node) * (n + 1));
	for(int t = 1; t <= n; ++ t) {
		int op; scanf("%d", &op);
		if(op == 1) {
			char tad[10]; scanf("%s", tad);
			insert(find(tad));
		} else if(op == 2) {
			char tad[10]; scanf("%s", tad);
			del(tad);
		} else {
			char s[10], t[10]; scanf("%s %s", s, t);
			swap(find(s), find(t));
		}
	}
	for(int i = list[0].next; i; i = list[i].next) {
		printf("%s %d\n", list[i].addr, list[i].val);
	}
	return 0;
}

J 神秘的礼物盒Ⅲ

命题人的得意之作,如果你会递归这题就会很简单,不会的话就非常难。然后你会发现其实那个 没有什么用。

#include <stdio.h>
#define ll long long

ll n, ans;

ll solve() {
	int op;
	if(scanf("%d", &op) == EOF) return ans;
	if(op == 1) {
		char c; scanf("%s", &c);
		printf("(");
		ll x = solve();
		printf(" %c ", c);
		ll y = solve();
		printf(")");
		if(c == '+') ans = x + y;
		if(c == '-') ans = x - y;
		if(c == '*') ans = x * y;
		if(c == '/') ans = x / y;
		return ans;
	} else {
		ll x; scanf("%lld", &x);
		printf("%lld", x);
		return x;
	}
	return 0;
}

int main()
{
	int n; scanf("%d", &n);
	printf("\n%lld", solve());
	return 0;
}