本题解并非按照周赛题目顺序撰写,请按照题目名称辨别。
A.喂喂,你知道魔法少女的这个传闻吗?
纯签到题,可以直接用程序计算并输出。
#include <bits/stdc++.h>
using namespace std;
int main()
{
cout << 4 * (11 * 4514 + 114 * 514 + 1145 * 14) << endl;
return 0;
}
B.这就是绝交证明书
本题数据量较大,如果暴力模拟会导致时间超限。
所以使用一个比较简单的算法来处理——前缀和。
以题解代码为例:数组cnt中cnt[i](1 <= i <= n)表示为第1到第i级台阶共写有的名字个数。
则 cnt[r] - cnt[l-1] 即表示为第l到第r级台阶共写有的名字个数。
每次询问只需要进行一次减法运算即可,相比遍历求和大大减少了时间复杂度。
有兴趣的同学可以了解一下:https://blog.csdn.net/qq_52156445/article/details/115839679
#include <stdio.h>
int cnt[100010] = {0};
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
int temp;
scanf("%d", &temp);
cnt[i] = cnt[i - 1] + temp;
}
int t;
scanf("%d", &t);
while (t--)
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", cnt[r] - cnt[l - 1]);
}
return 0;
}
C.我们之间没有你插手的余地哦?
!!!字符串可能会全由空格字符组成,用scanf中读入\n的方法读掉换行会导致空格字符串被忽略!!!
代码实例:
scanf("%d\n", &n); // 该方法会忽略第二行的纯空格字符串
scanf("%d", &n);
getchar(); // 用getchar只会读掉换行符
多实例的字符串题目,需要选择合适的读入方式,思路题(方法不唯一)。
需要说明的是,这些情况不表示为两个人之间存在且只存在空隙:“a11a", "aa1 0 1aa"。
这里通过定义一个flag旗帜,flag不同的值代表不同的状态。
- 当遍历找到一个'1'时,记录下当前坐标后继续遍历后面的位置(即代码中的内层for循环)如果其后一个位置是空隙则使flag为1。
- 如果内层for循环找到第二个'1'时flag为1,则使flag为2,如果flag不为1(0)则退出该循环。
- 如果内层for循环找到非空隙且非'1'字符则退出循环。 最后通过flag的值判断输出Y/N即可。
这里分享一个来自lcl学长(%%%)的解法,很有意思,感兴趣的同学可以看看:https://pastebin.ubuntu.com/p/TsQcR3wY2t/
#include <stdio.h>
#include <string.h>
int a[100010] = {0};
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n;
scanf("%d", &n);
getchar();
char s[110];
gets(s);
int len = strlen(s);
int flag = 0;
for (int i = 0; i < len; i++)
{
flag = 0;
if (s[i] == '1')
{
for (int j = i + 1; j < len; j++)
{
if (s[j] == ' ')
flag = 1;
else if (s[j] == '1')
{
if (flag == 1)
{
flag = 2;
break;
}
}
else
break;
}
if (flag == 2)
{
printf("Y\n");
break;
}
}
}
if (!flag)
printf("N\n");
}
return 0;
}
D.我什么都愿意做
直接按照活动的收益逆序排序然后求出前n个收益的和即可。
感兴趣的同学可以去了解一下不同的排序方法。
PS:因为数据大小问题需要使用long long。
#include <stdio.h>
long long a[10010] = {0};
int main()
{
int n;
scanf("%d", &n);
int t;
scanf("%d", &t);
for (int i = 0; i < t; i++)
scanf("%lld", &a[i]);
for (int i = 0; i < t - 1; i++)
for (int j = i + 1; j < t; j++)
if (a[i] < a[j])
{
long long t = a[i];
a[i] = a[j];
a[j] = t;
}
long long ans = 0;
for (int i = 0; i < n; i++)
ans += a[i];
printf("%lld\n", ans);
return 0;
}
E.绝对不能回邮件哦
判断字符然后输出对应的字符串即可。
需要注意的是输入字符串会包含空格,以及输出对空格要单独处理。
#include <stdio.h>
#include <string.h>
char a[27][5] = {
"01",
"1000",
"1010",
"100",
"0",
"0010",
"110",
"0000",
"00",
"0111",
"101",
"0100",
"11",
"10",
"111",
"0110",
"1101",
"010",
"000",
"1",
"001",
"0001",
"011",
"1001",
"1011",
"1100"};
int main()
{
char str[1010];
gets(str);
int len = strlen(str);
for (int i = 0; i < len; i++)
{
if (str[i] == ' ')
printf(" ");
else
printf("%s", a[str[i] - 'A']);
}
return 0;
}
F.我的名字
第二道签到题。
只要注意不分大小写即可。
#include <stdio.h>
#include <string.h>
int main()
{
char s[10010];
scanf("%s", s);
int len = strlen(s);
int m = 0, t = 0, l = 0, f = 0; // 分别记录mtlf的个数
for (int i = 0; i < len; i++)
{
if (s[i] == 'M' || s[i] == 'm')
m++;
else if (s[i] == 'T' || s[i] == 't')
t++;
else if (s[i] == 'L' || s[i] == 'l')
l++;
else if (s[i] == 'F' || s[i] == 'f')
f++;
}
while (m || t || l || f)
{
if (m > 0)
{
printf("m");
m--;
}
if (t > 0)
{
printf("t");
t--;
}
if (l > 0)
{
printf("l");
l--;
}
if (f > 0)
{
printf("f");
f--;
}
}
return 0;
}
G.约好了下午三点,在记忆博物馆
首先非常抱歉题目测试数据出了问题TT,会导致某些算法WA,题解这里是直接模拟。
这里先分享软件2022级的万明浩同学的解法,我认为比我写的要更简单一点。
#include<stdio.h>
int main()
{
int n,T,t=0,num=1,i,station[13][2]={0},s=0;
scanf("%d%d",&n,&T);
for(i=0;i<T;i++){
int a,b,x;
scanf("%d%d%d",&a,&b,&x);
station[a][0]=b;
station[a][1]=x;
}
while(1){
s++;
if(s>100){
num=0;
break;
}
t+=station[num][1];
num=station[num][0];
if(num==0||num==n)
break;
}
if(num!=n)
printf("No\n0");
else if(num==n&&t>120)
printf("No\n%d",t);
else
printf("yes\n%d",t);
return 0;
}
有一点难度,但是不涉及算法(也可以使用最短路的方法,但是有点大材小用)。
这里巧妙定义一个二维数组flag[13][13],flag[a][b]即可表示为一条从a站到b站的列车的用时。
之后只需要模拟判断是否到站/无路可走即可(看代码)。
需要注意的是每个站点只能作为一次起点这个条件十分重要,因为这样你到达记忆博物馆的路线只能是一条或没有。
#include <stdio.h>
#include <string.h>
int main()
{
int flag[13][13] = {0};
int n, t;
scanf("%d%d", &n, &t);
while (t--)
{
int a, b, x;
scanf("%d%d%d", &a, &b, &x);
flag[a][b] = x;
}
int crt = 1, cnt = 0; // 分别为当前所在位置和用时
while (1) // 一个死循环,break退出
{
int f = 0; // 判断是否找到路
for (int i = 1; i <= 12; i++)
{
if (flag[crt][i])
{
cnt += flag[crt][i];
flag[crt][i] = 0; // 使用后归零,防止死循环
crt = i;
f = 1;
break;
}
}
if (!f) // 没找到路直接输出No结束
{
printf("No\n0");
return 0;
}
if (crt == n)
{
if (cnt <= 120)
{
printf("yes\n%d", cnt);
return 0;
}
else
{
printf("No\n%d", cnt);
return 0;
}
}
}
}
H.唯一的道标
数学题,直接比较所在位置和四个出口的距离即可。
需要注意的是浮点数和输出格式是没有小数点及之后的数的。
#include <stdio.h>
#include <string.h>
#include <math.h>
double caculateDistance(double a, double b, double c, double d)
{
return (a - c) * (a - c) + (b - d) * (b - d);
}
int main()
{
double n, m, a, b;
scanf("%lf%lf%lf%lf", &n, &m, &a, &b);
double x[4] = {n / 2, n, n / 2, 0}, y[4] = {0, m / 2, m, m / 2};
double min = caculateDistance(a, b, x[0], y[0]);
int flag = 0;
for (int i = 1; i < 4; i++)
{
double temp = caculateDistance(a, b, x[i], y[i]);
if (min > temp)
{
min = temp;
flag = i;
}
}
printf("(%.0f, %.0f)", x[flag], y[flag]);
return 0;
}