本题解并非按照周赛题目顺序撰写,请按照题目名称辨别。

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级的万明浩同学的解法,我认为比我写的要更简单一点。
alt

#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;
}