洛阳师范学院 ACM实验室 中秋娱乐赛“月饼代码大逃杀”题解

lyx9785 / 2024-09-18 / 原文

题解包括C和C++两种语言_

壹 我要洋人死!

1、直接输出即可

C语言题解:

#include <stdio.h>
int main (){
    printf("woyaoyangrensi!");
    return 0;
}

C++语言题解:

#include<iostream>
using namespace std;
int main(){
	printf("woyaoyangrensi!");
	return 0;
}

贰 学长的馈赠

1、注意转义字符,直接输出即可

C语言题解:

#include <stdio.h>
int main (){
    printf("printf(\"Hello, World!\");");
    return 0;
}

C++题解:

#include<iostream>
using namespace std;
int main(){
	cout << "printf(\"Hello, World!\");";
	return 0;
}

叁 A+B AGAIN?

1、因为有t个测试用例,所以我们用循环解决

2、在每次循环中用除法和取模分别取出个位和十位,将其相加,输出结果

C语言题解:

#include <stdio.h>
int main (){
    //读入t
    int t; scanf("%d", &t);
    for(int i = 1; i <= t; ++i){
        //读入数字
        int num; scanf("%d",&num);
        //计算十位上的数字
		int TenBits = num / 10;
        //计算个位上的数字
        int Bits = num % 10;
        printf("%d\n",TenBits + Bits);
    }
    return 0;
}

C++题解:

#include <bits/stdc++.h>
using namespace std;
int main ()
{
    //读入t
	int t; cin >> t;
	for (int i = 1; i <= t; ++i)
	{
        //读入数字
        int num; cin >> num;
        //计算十位上的数字
		int TenBits = num / 10;
        //计算个位上的数字
        int Bits = num % 10;
        //输出二者相加的结果
		cout << TenBits + Bits << endl;
	}
	return 0;
}

肆 鸡兔同笼,但是兔兔太可爱了,换成小马!

小学就学过的“鸡兔同笼”问题,忘记的可以自行搜索一下

C语言题解:

#include <stdio.h>

int main() {
    int n, m;
    // 输入动物总数和腿的总数
    scanf("%d %d", &n, &m);

    // 判断腿数是否为偶数
    if (m % 2 != 0) {
        printf("No solution\n");
        return 0;
    }

    // 计算鸡和兔子的数量
    //假设所有动物全为四条腿,减去当前的腿数量
    //剩下的就是所有坤坤腿的数量,再除以二就算出了鸡的数量
    int x = (4 * n - m) / 2; // 鸡的数量
    //马的数量就自然得出来了
    int y = n - x;           // 马的数量

    // 判断数量是否为非负数
    if (x >= 0 && y >= 0) {
        printf("%d %d\n", x, y);
    } else {
        printf("No solution\n");
    }
    
    return 0;
}

C++语言题解:

#include <iostream>
using namespace std;
int main() {
    int n, m;
    // 输入动物总数和腿的总数
    cin >> n >> m;

    // 判断腿数是否为偶数
    if (m % 2 != 0) {
        cout << "No solution" << endl;
        return 0;
    }

    // 计算鸡和兔子的数量
    // 假设所有动物全为四条腿,减去当前的腿数量
    // 剩下的就是所有坤坤腿的数量,再除以二就算出了鸡的数量
    int x = (4 * n - m) / 2; // 鸡的数量
    // 马的数量就自然得出来了
    int y = n - x;           // 马的数量

    // 判断数量是否为非负数
    if (x >= 0 && y >= 0) {
        cout << x << " " << y << endl;
    } else {
        cout << "No solution" << endl;
    }

    return 0;
}

伍 重生之我在洛师当伍仁王

读入然后判断首尾字符是否一致就行了

C语言题解:

#include <stdio.h>
int main()
{  
   int t; scanf("%d",&t);
   char str[110];
   for (int i = 0; i < t; ++i) {
       int n; scanf("%d",&n);
       for (int j = 0; j < n ; ++j) {
           scanf(" %c",&str[j]);
       }
       if (str[0]!=str[n-1]) {
          printf("YES\n");
       } else {
          printf("NO\n");
       }
   }
   return 0;
}

C++题解:

#include <iostream>
using namespace std;
int main(){
    int t; cin >> t;
    for(int i = 0; i < t; ++i){
        int n; cin >> n;
        string ss; cin >> ss;
        if(ss[0] != ss[n - 1]){
            cout << "YES" << endl;
        } else {
            cout << "NO" << endl;
        }
    }
    return 0;
}

陆 丸辣!这月饼怎么吃不完口牙

按要求一步一步计算,最后向上取整就可以了

C语言题解:

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

int main() {
    double ans;
    int n;
    // 输入初始值和数量
    scanf("%lf %d", &ans, &n);
    for (int i = 0; i < n; ++i) {
        double x;
        scanf("%lf", &x);
        ans += x;  // 累加
    }
    // 输出结果的向上取整
    printf("%.0lf", ceil(ans));
    return 0;
}

C++题解:

#include<bits/stdc++.h>
using namespace std;
int main(){
    double ans;
    int n;
    cin >> ans >> n;
    for(int i = 0; i < n; ++i){
        double x; cin >> x;
        ans = ans + x;
    }
    cout << ceil(ans) ;
    return 0;
}

柒 哥们,她和别人不一样

先读入两个进行判断大多数的数,之后查找就行了

C语言题解:

#include <stdio.h>
int num[10010];
int main() {
    int n;
    scanf("%d", &n);
    
    // 读取前两个数
    scanf("%d %d", &num[0], &num[1]);
    
    if (num[0] == num[1]) {
        // 如果前两个数相等,继续遍历后续数字
        for (int i = 2; i < n; ++i) {
            scanf("%d", &num[i]);
            if (num[i] != num[0]) {
                printf("%d", i);  // 输出下标(0-based)
                return 0;
            }
        }
    } else {
        // 如果前两个数不相等,读取第三个数并判断
        scanf("%d", &num[2]);
        if (num[2] == num[1]) {
            printf("%d", num[0]);  // num[0] 是与众不同的数
        } else {
            printf("%d", num[1]);  // num[1] 是与众不同的数
        }
    }
    
    return 0;
}

C++语言题解:

#include <iostream>
using namespace std;
int num[10010];
int main()
{
    int n; cin >> n;
    cin >> num[0] >> num[1];
    if(num[0] == num[1]){
        for(int i = 2; i < n; ++i){
            cin >> num[i];
            if(num[i] != num[0]){
                cout << i ;
                return 0;
            }
        }
    }else{
        cin >> num[2];
        cout << (num[2] == num[1] ? 0 : 1);
    }
    return 0;
}

捌 放松,头晕是正常的。

普通的暴力计算会超时,因此我们引入一个全新的算法——前缀和

前缀和(Prefix Sum)是一种常用的算法技巧,主要用于快速计算数组中某个区间的元素和。它通过预处理,将数组的累积和存储起来,之后可以在常数时间内计算任意区间的和。这在处理多次区间查询时非常高效。

1、前缀和的定义

给定一个数组 arr,其前缀和数组 prefix_sum 的定义是:

prefix_sum[i] = arr[0] + arr[1] + ... + arr[i-1]

prefix_sum[i] 表示从数组起点 arr[0]arr[i-1] 的所有元素的累积和。

2、计算步骤

  1. 预处理前缀和数组

    • 初始化 prefix_sum[0] = 0(表示前 0 个元素的和为 0)。
  • 从第 1 个位置开始依次累加当前元素的值到 prefix_sum 中。
  1. 快速求任意区间和
    如果要计算数组中从位置 lr(包括 lr)之间的区间和,可以用:

    sum(l, r) = prefix_sum[r+1] - prefix_sum[l]
    

    通过前缀和数组,可以在 O(1) 的时间复杂度内计算任意区间的和。

3、示例

假设有数组 arr = [3, 2, 1, 4, 5],它的前缀和数组为:

prefix_sum[0] = 0
prefix_sum[1] = 3
prefix_sum[2] = 3 + 2 = 5
prefix_sum[3] = 3 + 2 + 1 = 6
prefix_sum[4] = 3 + 2 + 1 + 4 = 10
prefix_sum[5] = 3 + 2 + 1 + 4 + 5 = 15

假设要计算区间 [1, 3] 的和,即 arr[1] + arr[2] + arr[3],通过前缀和数组,我们可以得到:

sum(1, 3) = prefix_sum[4] - prefix_sum[1] = 10 - 3 = 7

4、前缀和的优点

  • 快速查询:对于多个区间和查询,前缀和方法可以在预处理 O(n) 的时间复杂度下,将后续的每次查询优化到 O(1)。
  • 适用场景:适用于频繁的区间和查询,如处理大量区间查询问题或数据统计问题。

通过前缀和技术,很多涉及连续区间操作的问题都可以得到高效解决。

如果没看懂的话可以在网上搜索教学视频自行学习

5、本题题解

C语言题解:

#include <stdio.h>
long long arr[100005];  // 存储输入的数字
long long prefixSum[100005];  // 存储前缀和

int main() {
    int n, q;
    
    // 读入 n 和 q
    scanf("%d %d", &n, &q);
    
    // 读入数组
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &arr[i]);
    }
    
    // 计算前缀和
    prefixSum[0] = 0;
    for (int i = 1; i <= n; i++) {
        prefixSum[i] = prefixSum[i - 1] + arr[i];
    }
    
    // 处理每一个查询
    while (q--) {
        int f, t;
        scanf("%d %d", &f, &t);
        // 利用前缀和快速求区间和
        printf("%lld\n", prefixSum[t] - prefixSum[f - 1]);
    }
    
    return 0;
}

C++题解:

#include <iostream>
using namespace std;
long long arr[100005];  // 存储输入的数字
long long prefixSum[100005];  // 存储前缀和

int main() {
    int n, q; cin >> n >> q;
    // 读入数组
    for (int i = 1; i <= n; i++) cin >> arr[i];
    
    // 计算前缀和
    prefixSum[0] = 0;
    for (int i = 1; i <= n; i++) prefixSum[i] = prefixSum[i - 1] + arr[i];
   
    // 处理每一个查询
    while (q--) {
        int f, t; cin >> f >> t;
        // 利用前缀和快速求区间和
        cout << prefixSum[t] - prefixSum[f - 1] << endl;
    }
    
    return 0;
}

玖 圣杯战争

贪心考虑:

<1>可以先将长度大于1且全为0的区间进行操作,这样可以尽可能减小0的数量(因为我们想让最终得到的区间1尽可能的多)

<2>操作完成后对剩余的0和1数量进行统计,如果1的数量不大于0,那么就无法通过操作得到a = [1](可以自己画一下,很容易就能得到这个结论)

C语言题解:

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

int main() {
    int t;
    scanf("%d", &t);  // 读取测试用例的数量
    while (t--) {
        int n;
        scanf("%d", &n);  // 读取字符串的长度
        char s[200005];  // 假设字符串长度不超过 100000
        scanf("%s", s);  // 读取字符串

        // 处理字符串,删除相邻的 '0'
        int newLength = 0;  // 新字符串的长度
        for (int i = 0; i < n; i++) {
            if (s[i] == '0' && (i > 0 && s[i - 1] == '0')) {
                // 跳过当前 '0'
                continue;
            }
            s[newLength++] = s[i];  // 将有效字符放入新位置
        }
        s[newLength] = '\0';  // 终止新字符串

        // 统计 '0' 和 '1' 的数量
        int c0 = 0, c1 = 0;
        for (int i = 0; i < newLength; i++) {
            if (s[i] == '0')
                c0++;
            else
                c1++;
        }

        // 输出结果
        if (c0 >= c1)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}

C++语言题解:

#include <iostream>
#include <string>
using namespace std;

int main() {
    int t;
    cin >> t;  // 读取测试用例的数量
    while (t--) {
        int n;
        cin >> n;  // 读取字符串的长度
        string s;  
        cin >> s;  // 读取字符串

        // 处理字符串,删除相邻的 '0'
        string new_s;  // 新字符串
        for (int i = 0; i < n; i++) {
            if (s[i] == '0' && (i > 0 && s[i - 1] == '0')) {
                // 跳过当前 '0'
                continue;
            }
            new_s += s[i];  // 将有效字符添加到新字符串中
        }

        // 统计 '0' 和 '1' 的数量
        int c0 = 0, c1 = 0;
        for (int i = 0; i < new_s.length(); i++) {
            if (new_s[i] == '0')
                c0++;
            else
                c1++;
        }
        // 输出结果
        if (c0 >= c1)
            cout << "NO" << endl;
        else
            cout << "YES" << endl;
    }
    return 0;
}

拾 这题真是签到题

读入时间,计算两个时间的时间差,并将这个时间差转换为秒为单位

时间差(秒) = 小时差 * 3600 + 分钟差 * 60 + 秒差

最后再用n乘上这个时间差就行了;

记得开long long!

C语言题解:

#include <stdio.h>
long long a,b,c,x,y,z,t;
int main(){
	scanf("%lld:%lld:%lld",&a,&b,&c);//scanf的独特
	scanf("%lld:%lld:%lld",&x,&y,&z);//输入办法哟!
    scanf("%lld",&t);
    printf("%lld",((x-a)*3600+(y-b)*60+(z-c))*t);
    return 0;
}

C++题解:

#include <iostream>
using namespace std;
long long a,b,c,x,y,z,t;
char m;
int main(){
    cin>>a>>m>>b>>m>>c>>x>>m>>y>>m>>z>>t; //读入
    cout<<((x-a)*3600+(y-b)*60+(z-c))*t; //时分秒的转换兼输出
    return 0;
} 

完结撒花!!!