GESP认证C++编程真题解析 | 202409 三级

编程题

B4038 平衡序列

【题目来源】

洛谷:[B4038 GESP202409 三级] 平衡序列 - 洛谷

【题目描述】

小杨有一个包含\(n\)个正整数的序列\(a\)。他认为一个序列是平衡的当且仅当存在一个正整数\(i (1≤i<n)\)使得序列前\(i\)个数字的和等于第 \(i+1\) 到第\(n\)个数字的总和。

【输入】

第一行包含一个正整数\(t\),代表测试用例数。

接下来是\(t\)组测试用例。对每组测试用例,共两行。

第一行包含一个正整数\(n\),代表序列长度。

第二行包含\(n\) 个正整数,代表序列 \(a\)

【输出】

对于每组测试用例,如果序列\(a\)是平衡的,输出"Yes",否则输出"No"。

【输入样例】

3
3
1 2 3
4
2 3 1 4
5
1 2 3 4 5

【输出样例】

Yes
Yes
No

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int a[10010], t;  // a: 存储数字的数组, t: 测试用例数量

int main()
{
    cin >> t;  // 输入测试用例数量
    
    while (t--)  // 处理每个测试用例
    {
        int n;  // 当前测试用例的数字个数
        cin >> n;
        
        int sum = 0;  // 所有数字的总和
        
        // 读入n个数字并计算总和
        for (int i = 1; i <= n; i++) 
        {
            cin >> a[i];
            sum += a[i];
        }
        
        int tot = 0;  // 前缀和
        int fl = 0;   // 标志位,0表示未找到,1表示找到
        
        // 寻找分割点
        for (int i = 1; i < n; i++)  // i从1到n-1
        {
            tot += a[i];  // 计算a[1]到a[i]的和
            
            // 如果前i个数的和等于总和的一半
            if (tot * 2 == sum) 
            {
                fl = 1;  // 设置标志位
                break;   // 找到就提前退出
            }
        }
        
        // 输出结果
        if (fl) 
            cout << "Yes" << endl;  // 找到分割点
        else 
            cout << "No" << endl;   // 未找到分割点
    }
    
    return 0;
}

【运行结果】

3
3
1 2 3
Yes
4
2 3 1 4
Yes
5
1 2 3 4 5
No

B4039 回文拼接

【题目来源】

洛谷:[B4039 GESP202409 三级] 回文拼接 - 洛谷

【题目描述】

一个字符串是回文串,当且仅当该字符串从前往后读和从后往前读是一样的,例如,\(aabaa\)\(ccddcc\) 都是回文串,但 \(abcd\) 不是。

小杨有 \(n\) 个仅包含小写字母的字符串,他想请你编写程序判断每个字符串是否由两个长度至少为 \(2\) 的回文串前后拼接而成。

【输入】

第一行包含一个整数 \(n\),代表字符串数量。

接下来的\(n\)行,每行包含一个小写字母组成的字符串。

【输出】

对于每个字符串输出一行,如果该字符串能由两个长度至少为\(2\)的回文子串前后拼接而成文,则输出出"Yes",否则输出"No"。

【输入样例】

4
abcd
aabbb
aaac
abcdd

【输出样例】

No
Yes
No
No

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n, k;  // n: 字符串数量, k: 未使用

int main()
{
    cin >> n;  // 输入字符串数量
    
    for (int i = 1; i <= n; i++)  // 处理每个字符串
    {
        string s;
        cin >> s;  // 读入一个字符串
        
        int m = s.length();  // 获取字符串长度
        int fl = 0;  // 标志位,0表示不满足条件,1表示满足
        
        // 尝试所有可能的分割点j
        // j的取值范围是[2, m-2],因为两边都需要至少2个字符
        for (int j = 2; j <= m - 2; j++) 
        {
            // 将字符串s在位置j处分割成两个子串
            string s1 = s.substr(0, j);      // 前j个字符
            string s2 = s.substr(j, m - j);  // 从j开始到结束的字符
            
            // 反转s1和s2
            string t1 = "", t2 = "";
            for (int k = (int)s1.size() - 1; k >= 0; k--) 
                t1 += s1[k];  // 反转s1
            for (int k = (int)s2.size() - 1; k >= 0; k--) 
                t2 += s2[k];  // 反转s2
            
            // 检查反转后的字符串是否等于原字符串
            if (t1 == s1 && t2 == s2) 
            {
                fl = 1;  // 满足条件
                break;   // 找到就退出循环
            }
        }
        
        // 输出结果
        if (fl) 
            cout << "Yes" << endl;  // 存在这样的分割
        else 
            cout << "No" << endl;   // 不存在这样的分割
    }
    
    return 0;
}

【运行结果】

4
abcd
No
aabbb
Yes
aaac
No
abcdd
No
posted @ 2026-03-28 13:45  团爸讲算法  阅读(12)  评论(0)    收藏  举报