找回密码
 立即注册
查看: 28|回复: 0

2015年蓝桥杯国赛C组机器人繁殖题解析:高精度整数代码实现与解题思路

[复制链接]
  • 打卡等级:即来则安
  • 打卡总天数:28
  • 打卡月天数:2
  • 打卡总奖励:194
  • 最近打卡:2025-08-15 15:43:34

36

主题

2

回帖

2544

积分

VIP会员

积分
2544
发表于 2025-7-19 10:48:37 | 显示全部楼层 |阅读模式
一、题目解读
2015年蓝桥杯国赛C组“机器人繁殖”问题要求求解机器人按月繁殖的累计数量。题目设定初始机器人数量为a,每月新增b台,需计算n个月后总机器人数。由于繁殖数量可能呈指数级增长,普通整数类型无法存储结果,因此需采用高精度整数运算解决。
二、解题思路
核心在于自定义高精度整数类(BigInt),支持加法、减法及乘法操作。解题关键在于利用高精度加法模拟每月繁殖过程:每月总数为上月总数+新增数量,通过循环迭代计算n个月后的累计值。高精度处理避免了数据溢出,确保结果正确性。
三、解题步骤
1. 初始化:读入初始数量a、新增量b及月份n,将a、b转换为高精度整数对象。
2. 循环迭代:通过循环执行n次加法操作,每次将当前总数加上b,更新总数。
3. 输出结果:将最终高精度整数转换为字符串输出,确保格式正确。
四、代码与注释
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. using namespace std;

  5. // 高精度整数类
  6. class BigInt {
  7. private:
  8.     vector<int> digits;  // 存储数字各位(逆序)
  9.     bool isNegative;     // 负数标记

  10. public:
  11.     BigInt() : isNegative(false) {}  // 默认构造函数
  12.     BigInt(string s) {  // 字符串初始化
  13.         if (s.empty()) return;
  14.         isNegative = (s[0] == '-');  // 处理负号
  15.         for (int i = s.size() - 1; i >= (isNegative? 1 : 0); --i) {
  16.             digits.push_back(s[i] - '0');  // 逆序存储数字字符
  17.         }
  18.     }

  19.     // 加法
  20.     BigInt operator+(const BigInt& other) const {
  21.         BigInt result;
  22.         int carry = 0;  // 进位
  23.         int maxLen = max(digits.size(), other.digits.size());

  24.         for (int i = 0; i < maxLen || carry; ++i) {
  25.             int sum = carry;
  26.             if (i < digits.size()) sum += digits[i];
  27.             if (i < other.digits.size()) sum += other.digits[i];
  28.             result.digits.push_back(sum % 10);
  29.             carry = sum / 10;
  30.         }

  31.         return result;
  32.     }

  33.     // 减法
  34.     BigInt operator-(const BigInt& other) const {
  35.         BigInt result;
  36.         int borrow = 0;  // 借位

  37.         for (int i = 0; i < digits.size(); ++i) {
  38.             int diff = digits[i] - borrow;
  39.             if (i < other.digits.size()) diff -= other.digits[i];
  40.             if (diff < 0) {
  41.                 diff += 10;
  42.                 borrow = 1;
  43.             } else {
  44.                 borrow = 0;
  45.             }
  46.             result.digits.push_back(diff);
  47.         }

  48.         // 去除前导零
  49.         while (result.digits.size() > 1 && result.digits.back() == 0) {
  50.             result.digits.pop_back();
  51.         }

  52.         return result;
  53.     }

  54.     // 乘法
  55.     BigInt operator*(const BigInt& other) const {
  56.         BigInt result;
  57.         result.digits.resize(digits.size() + other.digits.size(), 0);
  58.         
  59.         for (int i = 0; i < digits.size(); ++i) {
  60.             int carry = 0;
  61.             for (int j = 0; j < other.digits.size() || carry; ++j) {
  62.                 long long product = result.digits[i + j] +
  63.                                    (long long)digits[i] * (j < other.digits.size() ? other.digits[j] : 0) +
  64.                                    carry;
  65.                 result.digits[i + j] = product % 10;
  66.                 carry = product / 10;
  67.             }
  68.         }
  69.         
  70.         // 去除前导零
  71.         while (result.digits.size() > 1 && result.digits.back() == 0) {
  72.             result.digits.pop_back();
  73.         }
  74.         
  75.         return result;
  76.     }
  77.    
  78.     // 除法
  79.     BigInt operator/(const BigInt& other) const {
  80.         BigInt quotient, remainder;
  81.         
  82.         for (int i = digits.size() - 1; i >= 0; --i) {
  83.             remainder = remainder * BigInt("10") + BigInt(to_string(digits[i]));
  84.             int count = 0;
  85.             while (remainder >= other) {
  86.                 remainder = remainder - other;
  87.                 count++;
  88.             }
  89.             quotient.digits.insert(quotient.digits.begin(), count);
  90.         }
  91.         
  92.         // 去除前导零
  93.         while (quotient.digits.size() > 1 && quotient.digits.back() == 0) {
  94.             quotient.digits.pop_back();
  95.         }
  96.         
  97.         return quotient;
  98.     }
  99.    
  100.     // 比较运算符
  101.     bool operator>=(const BigInt& other) const {
  102.         if (digits.size() != other.digits.size()) {
  103.             return digits.size() > other.digits.size();
  104.         }
  105.         for (int i = digits.size() - 1; i >= 0; --i) {
  106.             if (digits[i] != other.digits[i]) {
  107.                 return digits[i] > other.digits[i];
  108.             }
  109.         }
  110.         return true;
  111.     }
  112.    
  113.     // 输出
  114.     friend ostream& operator<<(ostream& os, const BigInt& num) {
  115.         for (int i = num.digits.size() - 1; i >= 0; --i) {
  116.             os << num.digits[i];
  117.         }
  118.         return os;
  119.     }
  120. };

  121. // 计算2的幂
  122. BigInt powerOfTwo(int n) {
  123.     BigInt result("1");
  124.     for (int i = 0; i < n; ++i) {
  125.         result = result * BigInt("2");
  126.     }
  127.     return result;
  128. }

  129. int main() {
  130.     int n;
  131.     string s_str;
  132.     cin >> n >> s_str;
  133.     BigInt s(s_str);
  134.    
  135.     // 计算分子部分: s + 2^(n+1) - n - 2
  136.     BigInt two_pow_n1 = powerOfTwo(n + 1);
  137.     BigInt numerator = s + two_pow_n1 - BigInt(to_string(n + 2));
  138.    
  139.     // 计算分母部分: 2^(n+1) - 1
  140.     BigInt denominator = two_pow_n1 - BigInt("1");
  141.    
  142.     // 计算结果: x = numerator / denominator
  143.     BigInt x = numerator / denominator;
  144.    
  145.     cout << x << endl;
  146.    
  147.     return 0;
  148. }
复制代码


五、总结
本解法通过高精度整数类高效处理大数运算,核心在于加法操作的迭代应用。代码设计简洁,通过vector存储数字各位,支持动态扩展,适用于类似需要大数计算的竞赛题目。同时,减法与乘**能的实现为扩展其他复杂运算提供了基础。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表