第五届上海市青少年算法竞赛 题解

第五届上海市青少年算法竞赛 题解
本次比赛涉及算法:字符串、贪心、枚举模拟、 m a p map map、数学、思维、栈、折半查找、广度优先搜索
今年比赛整体的题目难度和思维难度还是偏大的,对小朋友们的逻辑思维、分析能力和运用能力有一定要求,特别是最后一题要拿满分,对于细节的处理要考虑周全, 2 2 2小时的比赛时间确实有点太短了。

比赛时间:2024 年 4 月 6 日
比赛链接https://iai.sh.cn/contest/63

第一题:T1符号译码

标签:字符串、枚举模拟、 m a p map map
题意:给定 01 01 01串和字符之间的编码规则,给出一个 01 01 01字符串,要求输出对应的符号序列。
(字符串长度为 n n n 2 ≤ n ≤ 300000 2≤n≤300000 2n300000
题解:按照题意直接暴力模拟就好了,可以用 m a p map map优化下代码逻辑。下面给出两种的写法的代码。
代码
普通暴力版:

#include <bits/stdc++.h>
using namespace std;

int main() {
   
   
    string s;
    cin >> s;
    int n = s.size();
    for (int i = 0; i < n; i++) {
   
   
        if (s[i] == '0' && s[i+1] == '1' && s[i+2] == '0') {
   
   
            cout << '[';
            i += 2;
        }
        else if (s[i] == '1' && s[i+1] == '0' && s[i+2] == '1') {
   
   
            cout << ']';
            i += 2;
        }
        else if (s[i] == '0' && s[i+1] == '0') {
   
   
            cout << '<';
            i += 1;
        }
        else if (s[i] == '1' && s[i+1] == '1') {
   
   
            cout << '>';
            i += 1;
        }
        else if (s[i] == '0' && s[i+1] == '1' && s[i+2] == '1') {
   
   
            cout << '+';
            i += 2;
        }
        else if (s[i] == '1' && s[i+1] == '0' && s[i+2] == '0') {
   
   
            cout << '-';
            i += 2;
        }
    }
    return 0;
}

简洁版、 m a p map map优化版:

#include <bits/stdc++.h>
using namespace std;

map<string, char> m;

int main() {
   
   
    // map预记录
    m["010"] = '['; m["101"] = ']';
    m["00"] = '<'; m["11"] = '>';
    m["011"] = '+'; m["100"] = '-';
    string s;
    cin >> s;
    int n = s.size();
    for (int i = 0; i < n; i++) {
   
   
        if (m[s.substr(i, 3)]) {
   
   
            cout << m[s.substr(i, 3)];
            i += 2;
        }
        else if (m[s.substr(i, 2)]) {
   
   
            cout << m[s.substr(i, 2)];
            i += 1;
        }
    }
    return 0;
}

第二题:T2数对排序

标签:数学、思维
题意:由两个自然数组成的一对数称之为有序数对,有序是指数对的第一项与第二项是区别的,例如 ( 0 , 1 ) (0,1) (0,1) ( 1 , 0 ) (1,0) (1,0)是不一样的数对。对所有有序数对进行排序,先按照每对中两数之和从小到大排序,两数之和相同,再按照每个数对中第一个数从小到大排序。
例如前 6 6 6个数对为 ( 0 , 0 ) , ( 0 , 1 ) , ( 1 , 0 ) , ( 0 , 2 ) , ( 1 , 1 ) , ( 2 , 0 ) (0,0), (0,1), (1,0), (0,2), (1,1), (2,0) (0,0),(0,1),(1,0),(0,2),(1,1),(2,0)
给定一个整数 k k k,求出第 k k k个数对。 ( 1 ≤ k ≤ 1 , 000 , 000 , 000 ) (1≤k≤1,000,000,000) (1k1,000,000,000)
题解:我们列一下前几个,找下规律:
( 0 , 0 ) (0,0) (0,0) ( 0 , 1 ) , ( 1 , 0 ) (0,1), (1,0) (0,1),(1,0) ( 0 , 2 ) , ( 1 , 1 ) , ( 2 , 0 ) (0,2), (1,1), (2,0) (0,2),(1,1),(2,0) ( 0 , 3 ) , ( 1 , 2 ) , ( 2 , 1 ) , ( 3 , 0 ) (0,3), (1,2), (2,1),(3,0)

<think>嗯,用户想找第二届上海市青少年算法竞赛小学组T2买二送一的题目和解题思路。首先,我需要确认这个比的具体信息,比如举办时间、题目的具体内容。不过根据用户提供的现有引用,目前只有上海计算机学会12月月和2023年8月月的资料,可能还没有关于第二届小学组竞赛的公开资料。不过,可能需要根据常见的“买二送一”类型题目来推测可能的解法和思路。 首先,“买二送一”通常属于贪心算法或数学优化的范畴。题目可能要求计算在购买一定数量商品时,如何利用优惠获得最小总价。例如,每买两个商品可以免费获得一个,或者类似的促销策略。常见解法是按降序排序,每三个一组处理,计算总价时需要减去最便宜的那个,或者类似的策略。可能需要动态规划或者数学上的组合计算。 需要确认用户提到的比是否存在公开的题目,或者是否有其他用户分享过相关题解。如果找不到原题,可能需要根据常见模式构建一个示例问题,并给出相应的解法。比如,假设题目是购买n个商品,每买两个最贵的可以送一个最便宜的,求最少花费。这种情况下,解法通常是排序后按最优组合计算价格。 另外,考虑到是小学组的题目,难度可能不会太高,可能涉及到基本的循环和条件判断,或者简单的贪心策略。需要注意数据范围和取模等要求,但根据用户提供的引用中的其他题目,可能类似动态规划或数学方法。 总结来说,如果原题无法获取,可以构造一个典型的“买二送一”问题,并给出排序后分组处理的解法,同时建议用户确认题目具体要求,比如优惠方式、输入输出格式等,以便更准确地解答。</think>根据现有资料库,第二届上海市青少年算法竞赛小学组T2"买二送一"的具体题目描述尚未收录。但基于常见题型特征与竞赛规律,提供典型解法思路如下: ### 典型题目特征推测 题目可能要求:购买商品时,每购买两件价格最高的商品可免费获得一件价格最低的商品,需要计算购买全部商品的最小花费。输入为商品单价列表,输出最优方案总价。 ### 标准解法思路 1. **排序预处理** 将商品价格按降序排列,使得高价商品优先参与优惠组合。 2. **分组策略** 每三个商品为一组,其中前两个高价商品参与付费,第三个低价商品免费。例如排序后的价格序列:$$[a_1,a_2,a_3,...,a_{n}]$$ 其中 $$a_1 \geq a_2 \geq ... \geq a_n$$ 分组方式为:每组包含三个连续元素,前两个付费,第三个免费。 3. **计算总价** 遍历排序后的数组,累加所有非免费商品的价格。数学表达式: $$ \text{总价} = \sum_{i=1}^{n} a_i - \sum_{k=1}^{\lfloor n/3 \rfloor} a_{3k} $$ ### 参考代码模板 ```python n = int(input()) prices = list(map(int, input().split())) prices.sort(reverse=True) total = sum(prices) # 每三个一组减去最后一个的价格 for i in range(2, len(prices), 3): total -= prices[i] print(total) ``` ### 复杂度分析 - 时间复杂度:$O(n \log n)$ 主要来自排序操作 - 空间复杂度:$O(n)$ 存储价格列表
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值