当前位置: 首页 > news >正文

[蓝桥杯]小计算器

小计算器

题目描述

模拟程序型计算器,依次输入指令,可能包含的指令有

  1. 数字:'NUMX',X 为一个只包含大写字母和数字的字符串,表示一个当前进制的数。

  2. 运算指令:'ADD','SUB','MUL','DIV','MOD',分别表示加减乘,除法取商,除法取余。

  3. 进制转换指令:'CHANGE K',将当前进制转换为 K 进制(2≤K≤362≤K≤36)。

  4. 输出指令:'EQUAL',以当前进制输出结果。

  5. 重置指令:'CLEAR',清除当前数字。

指令按照以下规则给出:

数字,运算指令不会连续给出,进制转换指令,输出指令,重置指令有可能连续给出。

运算指令后出现的第一个数字,表示参与运算的数字。且在该运算指令和该数字中间不会出现运算指令和输出指令。

重置指令后出现的第一个数字,表示基础值。且在重置指令和第一个数字中间不会出现运算指令和输出指令。

进制转换指令可能出现在任何地方。

运算过程中中间变量均为非负整数,且小于 263263。

以大写的'A'~'Z'表示 10~35。

输入描述

第 1 行:1 个nn(1≤n<5×1051≤n<5×105),表示指令数量。

第 2 ⋯n+1⋯n+1行:每行给出一条指令。指令序列一定以'CLEAR'作为开始,并且满足指令规则。

初始默认的进制是十进制。

输出描述

依次输出每一次 'EQUAL' 得到的结果。

输入输出样例

示例

输入

7
CLEAR
NUM 1024
CHANGE 2
ADD
NUM 100000
CHANGE 8
EQUAL

输出

2040

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

总通过次数: 1075  |  总提交次数: 1304  |  通过率: 82.4%

难度: 困难   标签: 2017, 模拟, 国赛

算法思路:状态机与进制转换

本问题需要实现一个支持多进制运算的程序型计算器,核心挑战在于:

  1. ​多进制处理​​:支持2-36进制转换和数值表示
  2. ​状态管理​​:需要跟踪当前数值、操作符和进制状态
  3. ​大数运算​​:中间变量需支持2⁶³范围内的整数运算
  4. ​指令序列处理​​:按特定规则处理指令序列

采用​​状态机模型​​结合​​进制转换函数​​实现:

算法步骤

  1. ​初始化状态​​:

    • 当前值 current = 0
    • 操作符 op = ""
    • 进制 base = 10
    • 重置标志 after_clear = true
  2. ​指令处理​​:

    • ​CLEAR​​:重置状态,标记下一个NUM为基础值
    • ​NUM X​​:
      • 若在CLEAR后,设为当前值
      • 若有待处理操作符,执行运算
    • ​运算指令​​:记录操作符,等待操作数
    • ​CHANGE K​​:更新当前进制
    • ​EQUAL​​:将当前值转换为当前进制字符串输出
  3. ​进制转换​​:

    • 字符串→数值:按进制解析字符串
    • 数值→字符串:除基取余法转换

完整代码实现

#include <iostream>
#include <string>
#include <cctype>
#include <vector>
#include <algorithm>
using namespace std;// 字符串转数值(支持2-36进制)
long long strToNum(const string& s, int base) {long long num = 0;for (char c : s) {int digit = isdigit(c) ? c - '0' : c - 'A' + 10;num = num * base + digit;}return num;
}// 数值转字符串(支持2-36进制)
string numToStr(long long num, int base) {if (num == 0) return "0";string res;bool negative = num < 0;if (negative) num = -num;while (num) {int digit = num % base;res += (digit < 10) ? ('0' + digit) : ('A' + digit - 10);num /= base;}if (negative) res += '-';reverse(res.begin(), res.end());return res;
}int main() {ios::sync_with_stdio(false);cin.tie(0);int n;cin >> n;cin.ignore(); // 清除换行符long long current = 0;   // 当前数值string op = "";          // 当前操作符int base = 10;           // 当前进制bool after_clear = true; // CLEAR后标记for (int i = 0; i < n; i++) {string command;getline(cin, command);// 指令类型判断if (command == "CLEAR") {current = 0;op = "";after_clear = true;} else if (command.substr(0, 3) == "NUM") {string num_str = command.substr(4);long long num = strToNum(num_str, base);if (after_clear) {current = num;after_clear = false;} else if (!op.empty()) {if (op == "ADD") current += num;else if (op == "SUB") current -= num;else if (op == "MUL") current *= num;else if (op == "DIV") current /= num;else if (op == "MOD") current %= num;op = "";}}else if (command == "ADD") op = "ADD";else if (command == "SUB") op = "SUB";else if (command == "MUL") op = "MUL";else if (command == "DIV") op = "DIV";else if (command == "MOD") op = "MOD";else if (command.substr(0, 6) == "CHANGE") {base = stoi(command.substr(7));}else if (command == "EQUAL") {cout << numToStr(current, base) << endl;}}return 0;
}

代码解析

  1. ​核心函数​​:

    • strToNum():将字符串按指定进制转换为数值
    • numToStr():将数值转换为指定进制的字符串
  2. ​状态管理​​:

    • current:存储当前计算值
    • op:记录待处理的运算操作
    • after_clear:标记CLEAR后的特殊状态
  3. ​指令处理流程​​:

    • 使用getline读取完整指令
    • substr提取指令参数
    • 状态转换驱动计算过程
  4. ​进制转换​​:

    • 支持2-36进制(0-9,A-Z)
    • 正确处理负数和零值

实例验证(题目样例)

​输入​​:

7
CLEAR
NUM 1024      // 十进制1024
CHANGE 2      // 转为二进制
ADD           // 加法操作
NUM 100000    // 二进制100000 = 十进制32
CHANGE 8      // 转为八进制
EQUAL         // 输出结果

​处理过程​​:

  1. CLEAR:重置状态(current=0, after_clear=true)
  2. NUM 1024:设为当前值(current=1024)
  3. CHANGE 2:进制改为2
  4. ADD:设置操作符为加法
  5. NUM 100000
    • 将"100000"从二进制转为十进制:32
    • 执行加法:1024 + 32 = 1056
  6. CHANGE 8:进制改为8
  7. EQUAL:将1056转为八进制 → 2040

​输出​​:2040 ✓

注意事项

  1. ​进制边界处理​​:

    • 确保进制K在2-36范围内
    • 非法字符检测(如二进制出现'2')
  2. ​数值范围​​:

    • 使用long long(64位)存储中间结果
    • 检查运算溢出(题目保证<2⁶³)
  3. ​特殊运算​​:

    • 除法/取模时除数不能为0
    • 负数处理(题目要求非负整数)
  4. ​状态一致性​​:

    • CLEAR后必须重置操作符状态
    • 确保NUM指令在正确上下文中执行

多方位测试点

​测试类型​​测试数据​​预期结果​​验证要点​
基本运算ADD后接NUM 5正确求和基本运算功能
进制转换CHANGE 16NUM A十进制10字母数字转换
连续重置连续CLEAR指令状态正确重置状态机稳定性
边界数值NUM 9223372036854775807正确处理大数支持(2⁶³-1)
非法操作符UNKNOWN指令忽略或报错错误指令处理
除数为零DIV后接NUM 0异常处理除零保护机制
混合进制运算十进制+二进制值正确结果进制转换一致性
长指令序列10⁵条指令压力测试1秒内完成性能优化

优化建议

  1. ​预编译指令表​​:

    unordered_map<string, function<void()>> cmd_map = {{"CLEAR", [&](){ /* CLEAR处理 */ }},{"ADD",   [&](){ op = "ADD"; }}// ...其他指令
    };
  2. ​进制转换优化​​:

    // 使用查表法加速转换
    const char digits[36] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
    };
  3. ​运算批处理​​:

    // 支持连续运算(需修改题目规则)
    if (!op.empty() && !after_clear) {execute_pending_operation();
    }
  4. ​错误处理增强​​:

    try {base = stoi(command.substr(7));if (base < 2 || base > 36) throw out_of_range("");
    } catch (...) {cerr << "Invalid base: " << command.substr(7) << endl;
    }
  5. ​内存优化​​:

    // 预留指令存储空间
    vector<string> commands;
    commands.reserve(n);

相关文章:

  • 分布式互斥算法
  • sqli-labs靶场38-45关(堆叠注入)
  • Qt 中实现文本截断(ellipsis)的功能。Qt 提供了此方法来处理过长的文本显示问题,例如在界面中限制文本长度并添加省略号(...)
  • Flutter面试题
  • AI编程规范失控?三大策略用Cursor Rules精准约束
  • 边缘计算网关赋能沸石转轮运行故障智能诊断的配置实例
  • Redis常见使用场景解析
  • mysql 悲观锁和乐观锁(—悲观锁)
  • PLC远程控制网关支持多塘口水环境数据边缘计算与远程安全传输的配置指南
  • 对抗性提示:大型语言模型的安全性测试
  • 航芯MCU使用IAR+Jlink调试
  • C++ 类一
  • iTunes 无法备份 iPhone:10 种解决方法
  • Spring Framework 中 UriComponentsBuilder工具类
  • 设计模式-外观模式
  • 数学复习笔记 26
  • 【趣味Html】第11课:动态闪烁发光粒子五角星博客
  • 数据分析之OLTP vs OLAP
  • 【华为云学习与认证】以华为云物联网为基座的全栈开发(从物联网iot平台模块到应用展示、数据分析、机器学习、嵌入式开发等)的系统性学习与认证路线
  • Async-profiler 内存采样机制解析:从原理到实现
  • 黄岩做网站的公司/河南it渠道网
  • 内蒙古网络/爱站网seo工具包
  • 网站建设项目分析报告/免费发布友链
  • 祁阳网站建设/网站优化排名方法
  • 做网站主页效果图/优化大师优化项目有
  • cms开源建站系统/市场推广方案范文