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

深度学习
• 阅读 14

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

一、题目解读

2015年蓝桥杯国赛C组“机器人繁殖”问题要求求解机器人按月繁殖的累计数量。题目设定初始机器人数量为a,每月新增b台,需计算n个月后总机器人数。由于繁殖数量可能呈指数级增长,普通整数类型无法存储结果,因此需采用高精度整数运算解决。

二、解题思路

核心在于自定义高精度整数类(BigInt),支持加法、减法及乘法操作。解题关键在于利用高精度加法模拟每月繁殖过程:每月总数为上月总数+新增数量,通过循环迭代计算n个月后的累计值。高精度处理避免了数据溢出,确保结果正确性。

三、解题步骤

  1. 初始化:读入初始数量a、新增量b及月份n,将a、b转换为高精度整数对象。

  2. 循环迭代:通过循环执行n次加法操作,每次将当前总数加上b,更新总数。

  3. 输出结果:将最终高精度整数转换为字符串输出,确保格式正确。

四、代码与注释

#include <iostream>
#include <string>
#include <vector>
using namespace std;

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

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

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

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

        return result;
    }

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

        for (int i = 0; i < digits.size(); ++i) {
            int diff = digits[i] - borrow;
            if (i < other.digits.size()) diff -= other.digits[i];
            if (diff < 0) {
                diff += 10;
                borrow = 1;
            } else {
                borrow = 0;
            }
            result.digits.push_back(diff);
        }

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

        return result;
    }

    // 乘法
    BigInt operator*(const BigInt& other) const {
        BigInt result;
        result.digits.resize(digits.size() + other.digits.size(), 0);

        for (int i = 0; i < digits.size(); ++i) {
            int carry = 0;
            for (int j = 0; j < other.digits.size() || carry; ++j) {
                long long product = result.digits[i + j] + 
                                   (long long)digits[i] * (j < other.digits.size() ? other.digits[j] : 0) + 
                                   carry;
                result.digits[i + j] = product % 10;
                carry = product / 10;
            }
        }

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

        return result;
    }

    // 除法
    BigInt operator/(const BigInt& other) const {
        BigInt quotient, remainder;

        for (int i = digits.size() - 1; i >= 0; --i) {
            remainder = remainder * BigInt("10") + BigInt(to_string(digits[i]));
            int count = 0;
            while (remainder >= other) {
                remainder = remainder - other;
                count++;
            }
            quotient.digits.insert(quotient.digits.begin(), count);
        }

        // 去除前导零
        while (quotient.digits.size() > 1 && quotient.digits.back() == 0) {
            quotient.digits.pop_back();
        }

        return quotient;
    }

    // 比较运算符
    bool operator>=(const BigInt& other) const {
        if (digits.size() != other.digits.size()) {
            return digits.size() > other.digits.size();
        }
        for (int i = digits.size() - 1; i >= 0; --i) {
            if (digits[i] != other.digits[i]) {
                return digits[i] > other.digits[i];
            }
        }
        return true;
    }

    // 输出
    friend ostream& operator<<(ostream& os, const BigInt& num) {
        for (int i = num.digits.size() - 1; i >= 0; --i) {
            os << num.digits[i];
        }
        return os;
    }
};

// 计算2的幂
BigInt powerOfTwo(int n) {
    BigInt result("1");
    for (int i = 0; i < n; ++i) {
        result = result * BigInt("2");
    }
    return result;
}

int main() {
    int n;
    string s_str;
    cin >> n >> s_str;
    BigInt s(s_str);

    // 计算分子部分: s + 2^(n+1) - n - 2
    BigInt two_pow_n1 = powerOfTwo(n + 1);
    BigInt numerator = s + two_pow_n1 - BigInt(to_string(n + 2));

    // 计算分母部分: 2^(n+1) - 1
    BigInt denominator = two_pow_n1 - BigInt("1");

    // 计算结果: x = numerator / denominator
    BigInt x = numerator / denominator;

    cout << x << endl;

    return 0;
}

五、总结

本解法通过高精度整数类高效处理大数运算,核心在于加法操作的迭代应用。代码设计简洁,通过vector存储数字各位,支持动态扩展,适用于类似需要大数计算的竞赛题目。同时,减法与乘法功能的实现为扩展其他复杂运算提供了基础。

来源:蓝桥杯题解

点赞
收藏
评论区
推荐文章
可莉 可莉
3年前
16. 数值的整数次方(剑指 Offer 题解Java版)
文章目录16\.数值的整数次方题目链接题目描述解题思路实现代码16\.数值的整数次方题目链接NowCoder题目描述        给定一个double类型的浮点数
贾蔷 贾蔷
1个月前
2025年GESP七级等价消除(洛谷P11965)代码解析与优化策略
一、题目解读2025年GESP七级考试中的“等价消除(洛谷P11965)”问题要求统计给定字符串中满足等价条件的子串数量。所谓“等价子串”,是指子串中所有字符出现的次数均相同。题目需要高效算法解决,考验对字符串处理和状态压缩的掌握。二、解题思路采用位运算
贾蔷 贾蔷
3星期前
牛客12576题全解析:动态规划+质因数分解解决跳跃问题
一、题目解读牛客12576题是一道经典的算法题,要求给定起点N和终点M,求解从N到M的最少跳跃次数。题目考察的核心在于路径优化与动态规划思想,需结合数论中的质因数分解技巧,通过合理设计算法降低时间复杂度,避免暴力枚举的指数级耗时。二、解题思路采用“动态规划
深度学习 深度学习
3星期前
洛谷P2034题解:动态规划+单调队列优化求解最大K段子段和问题
一、题目解读洛谷P2034题目要求给定一个长度为n的整数数组,将其分成不超过k段,求各段和的最大值。该问题属于经典动态规划问题的扩展,需结合优化技巧高效求解。二、解题思路采用动态规划单调队列优化的策略。核心思想是定义状态dp
深度学习 深度学习
2星期前
2024年蓝桥杯国赛A组题 九宫格全解析:基于BFS算法的代码实现与优化
2024年蓝桥杯国赛A组题九宫格全解析:基于BFS算法的代码实现与优化蓝桥杯国赛九宫格问题BFS算法代码解析解题步骤第1张一、题目解读2024年蓝桥杯国A的九宫格题目(对应洛谷P10578)要求通过旋转九宫格中的2x2区域,实现从初始状态到目标状态的转换,
贾蔷 贾蔷
1星期前
牛客3750题滑动窗口最大值解析:双端队列优化解法与代码详解
一、题目解读要求在一个给定的整数中,计算固定大小为k的内元素的最大值。例如,当窗口滑动时,需要实时输出每个窗口中的最大值序列。该问题考察对的理解,以及如何高效维护窗口内的元素关系。二、解题思路采用(deque)维护的巧妙解法。核心思想是:中仅存储数组下标,
深度学习 深度学习
5天前
NOIP 2008火柴棒等式题解(C++代码实现) 动态规划与枚举算法详解
一、题目解读问题(,)要求使用给定数量的火柴棒,构造形如ABC的等式,其中A、B、C均为整数,且火柴棒总数恰好等于输入值。需统计符合条件的等式数量。题目核心在于将数字拆解与火柴棒消耗建模为数学问题,寻找高效解法。二、解题思路采用火柴棒计数策略:1.关系
贾蔷 贾蔷
4天前
洛谷1220题解:动态规划与区间DP优化解法
一、题目解读1220题要求计算在n个位置放置灯的情况下,通过关闭连续区间灯并移动至区间端点,使得总耗电量最小。需考虑灯的功率与位置差异,设计高效的求解最优策略。二、解题思路1.:定义状态dp:使用sum存储灯功率前缀和,简化区间电量计算。3.核心:○向左
贾蔷 贾蔷
4天前
牛客13278题详解:句子单词反转(C++实现)
一、题目解读13278题要求编写函数实现句子中单词顺序的反转,例如将"HelloWorld"转换为"WorldHello"。需注意处理首尾空格、单词间空格数量保持原样,仅单词顺序颠倒。题目考察对操作的掌握,特别是分割与重组技巧。二、解题思路采用:1.预处理
贾蔷 贾蔷
23小时前
CSP-J 2019纪念品题解(洛谷P5662):动态规划+完全背包问题的实战应用
一、题目解读2019年的“纪念品”问题(对应P5662)要求玩家在T天内通过买卖纪念品最大化金币收益。每天可交易N种商品,需计算最优策略下的最终金币数。题目强调思维与资源分配优化,是中的经典题型。二、解题思路核心思路为“动态规划”。每天将当前商品价格与次