信息学奥赛一本通 1413:确定进制 | OpenJudge NOI 1.13 34:确定进制

📅 2026/7/16 2:23:48
信息学奥赛一本通 1413:确定进制 | OpenJudge NOI 1.13 34:确定进制
1. 进制转换基础从生活到代码我们每天使用的十进制系统由0到9这十个数字组成逢十进一。但在计算机的世界里二进制0和1、八进制0到7和十六进制0到9加A到F才是更常见的表示方式。比如计算机底层用二进制处理数据而程序员调试时常用十六进制查看内存。理解不同进制间的转换原理是解决确定进制问题的关键。举个例子数字11在不同进制下表示的值完全不同二进制(2进制)1×2¹ 1×2⁰ 3八进制(8进制)1×8¹ 1×8⁰ 9十进制(10进制)就是我们熟悉的11在C中我们可以用标准库函数进行进制转换#include iostream #include string using namespace std; int main() { string num 11; // 将字符串从2进制转换为10进制 int decimal stoi(num, nullptr, 2); cout 二进制11等于十进制 decimal endl; return 0; }2. 问题解析如何确定正确的进制题目通常给出类似11 11 110这样的等式要求我们找出这个等式成立的最小进制。这里的核心思路是遍历可能的进制从最小可能开始将等式中的数字转换为该进制下的十进制值验证等式是否成立找到第一个使等式成立的进制举个例子对于11 11 110在2进制下3 3 6成立在3进制下4 4 12不成立 所以最小满足的进制是2。实际编程时要注意数字中出现的最大数字决定了进制的最小可能值如数字含5进制至少是6进制上限通常不需要太大一般不超过36因为数字加字母共36个符号3. 算法实现从暴力到优化最直接的解法是暴力枚举所有可能的进制#include iostream #include string #include algorithm using namespace std; // 将字符串s按base进制转换为十进制数 int toDecimal(const string s, int base) { int res 0; for (char c : s) { int digit isdigit(c) ? c - 0 : c - A 10; res res * base digit; } return res; } int findMinBase(string p, string q, string r) { // 找出三个数中最大的数字 char max_digit 0; for (char c : p q r) { if (c max_digit) max_digit c; } // 计算最小可能的进制 int min_base (isdigit(max_digit) ? max_digit - 0 : max_digit - A 10) 1; if (min_base 2) min_base 2; // 进制至少为2 for (int base min_base; base 36; base) { int a toDecimal(p, base); int b toDecimal(q, base); int c toDecimal(r, base); if (a b c) { return base; } } return -1; // 无解 }优化思路使用二分查找替代线性枚举当进制范围较大时提前计算数字的最大可能长度估算进制上限处理大数时可以用long long或自定义大数类4. 实战技巧与常见错误在实际比赛中这类题目有几个常见陷阱数字合法性检查在进制b下数字的每位必须小于b。比如12在2进制下是非法的。边界条件单个数字0在所有进制下都表示0数字10在任何进制下都等于该进制本身性能优化// 快速判断数字是否合法 bool isValid(const string s, int base) { for (char c : s) { int digit isdigit(c) ? c - 0 : c - A 10; if (digit base) return false; } return true; }特殊输入处理等式可能是减法或乘法数字可能包含小写字母需要统一转为大写前导零问题通常可以忽略我在第一次做这类题时曾因为没有考虑字母大小写而WA了三次。后来养成了统一转大写的习惯transform(s.begin(), s.end(), s.begin(), ::toupper);另一个常见错误是进制下界计算错误。比如数字2的最小进制是3而不是2因为2在2进制下是非法数字每位只能是0或1。