当前位置:首页 > 技术 > 正文内容

上海市计算机学会2023年1月月赛程序设计题解

访客 技术 2026年7月22日 3

T1 实验日志

题目描述:小爱进行物理实验持续n天,第i天记录a_i条实验数据。每页日志最多可记录m条数据。每天结束后合上日志,次日从第一页开始翻阅,直到找到第一个有空白位置的页面为止。求每天需要翻多少页才能找到起始记录位置。

解题思路:设截至当前已记录的数据总量为sum,则已写满的页数为sum/m(整数除法)。由于从下一页开始记录,因此需要翻动的页数即为sum/m。

参考实现

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

int main() {
    int n, m;
    cin >> n >> m;
    long long total = 0;
    for (int i = 0; i < n; ++i) {
        int x;
        cin >> x;
        cout << total / m << " ";
        total += x;
    }
    return 0;
}

T2 凯撒加密

题目描述:将明文中的每个英文字母向后移动3位得到密文,字母z之后循环回字母a。空格及其他非字母字符保持不变。

解题思路:遍历输入的每个字符,若是小写字母则转换为大写字母的对应密文字母,转换公式为:(c - 'a' + 3) % 26 + 'a'。

参考实现

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

int main() {
    string s;
    getline(cin, s);
    for (char &c : s) {
        if (c >= 'a' && c <= 'z') {
            c = (c - 'a' + 3) % 26 + 'a';
        } else if (c >= 'A' && c <= 'Z') {
            c = (c - 'A' + 3) % 26 + 'A';
        }
    }
    cout << s << endl;
    return 0;
}

T3 找零

题目描述:自动售票机每张票5元,可接受5元、10元、20元纸币。初始无零钱,顾客每人购买一张票且只投一张纸币。求最多能卖出多少张票。

解题思路:采用贪心策略。收到20元时优先找零一张10元和一张5元;收到10元时找零一张5元。使用变量记录当前拥有的5元、10元、20元数量。

参考实现

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

int main() {
    int n;
    cin >> n;
    int cnt5 = 0, cnt10 = 0, cnt20 = 0;
    int result = 0;
    
    for (int i = 0; i < n; ++i) {
        int bill;
        cin >> bill;
        int change_needed = bill - 5;
        
        // 先用20元找零
        int use20 = min(change_needed / 20, cnt20);
        change_needed -= use20 * 20;
        
        // 再用10元找零
        int use10 = min(change_needed / 10, cnt10);
        change_needed -= use10 * 10;
        
        // 最后用5元找零
        int use5 = change_needed / 5;
        
        if (use5 <= cnt5) {
            cnt20 -= use20;
            cnt10 -= use10;
            cnt5 -= use5;
            ++result;
            if (bill == 5) ++cnt5;
            else if (bill == 10) ++cnt10;
            else ++cnt20;
        }
    }
    
    cout << result << endl;
    return 0;
}

T4 新年灯会

题目描述:道路上有编号1到n的灯笼,现有p个灯笼不亮。求最少修复多少个灯笼,使得道路上存在连续m个亮着的灯笼。

解题思路:使用前缀和数组记录到每个位置为止不亮灯笼的总数。枚举所有长度为m的连续区间,计算每个区间内不亮灯笼的数量,取最小值即为答案。

参考实现

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

int main() {
    int n, m, p;
    cin >> n >> m >> p;
    vector<int> broken(n + 1, 0);
    
    for (int i = 0; i < p; ++i) {
        int x;
        cin >> x;
        broken[x] = 1;
    }
    
    vector<int> prefix(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        prefix[i] = prefix[i - 1] + broken[i];
    }
    
    int answer = INT_MAX;
    for (int i = 1; i <= n - m + 1; ++i) {
        int broken_in_range = prefix[i + m - 1] - prefix[i - 1];
        answer = min(answer, broken_in_range);
    }
    
    cout << answer << endl;
    return 0;
}

T5 积木染色(二)

题目描述:n块积木排成一排,有m种颜色可供染色。从第二块积木开始统计,恰有p块积木与前一块积木颜色不同。求满足条件的染色方案数模10^9+7。

解题思路:动态规划。定义dp[i][j]表示处理到第i块积木时,已有j块与前一块颜色不同的方案数。状态转移时考虑当前积木与前一块颜色相同或不同的情况。

参考实现

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;

int main() {
    int n, m, p;
    cin >> n >> m >> p;
    
    vector<vector<long long>> dp(n + 1, vector<long long>(p + 1, -1));
    
    function<long long(int, int)> solve = [&](int idx, int diff) -> long long {
        if (diff > p) return 0;
        if (idx == n) {
            return diff == p ? m : 0;
        }
        if (dp[idx][diff] != -1) return dp[idx][diff];
        
        long long result = solve(idx + 1, diff);
        result = (result + solve(idx + 1, diff + 1) * (m - 1) % MOD) % MOD;
        
        dp[idx][diff] = result;
        return result;
    };
    
    cout << solve(1, 0) << endl;
    return 0;
}

数学推导:设f(i,j)为处理到第i块积木时已有j个颜色不同的方案数。状态转移方程为:

  • 当j < p时:f(i,j) = f(i+1,j) + (m-1) × f(i+1,j+1)
  • 当j = p时:f(i,j) = f(i+1,j)

边界条件:处理完所有n块积木时,若恰好有p个不同则返回m(最后一块有m种颜色选择),否则返回0。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。