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

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

1个月前 (07-19)

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

一、题目解读

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存储数字各位,支持动态扩展,适用于类似需要大数计算的竞赛题目。同时,减法与乘法功能的实现为扩展其他复杂运算提供了基础。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣53题:贪心策略与动态规划的完美联姻 三行代码映射算法精髓

力扣53题:贪心策略与动态规划的完美联姻 三行代码映射算法精髓

题目理解在数字的海洋中寻找最具价值的珍珠链:当我们面对一个可能包含正负数的数组时,寻找连续子数组的和最大值就像在波动的股票曲线中捕捉最佳投资时段。问题的核心在于如何处理可能降低总和的负值元素——是忍痛...

用栈结构优雅破解括号匹配难题(力扣20题)

用栈结构优雅破解括号匹配难题(力扣20题)

一、题目重新解读给定一个仅包含 ('、')、'['、']'、'{'、'}' 的字符串,判断其是否有效。有效需满足:1....

线性遍历+二进制 6行代码征服二进制链表转整数

线性遍历+二进制 6行代码征服二进制链表转整数

力扣1290.二进制链表转整数题目本质给定一个单链表的头节点head,链表中每个节点的值为0或1。链表表示一个‌最高有效位在前‌的二进制数字,要求将其转换为对应的十进制整数。例如链表1→0→1对应的二...

【蓝桥杯国赛A组】冰山体积计算:动态规划与map统计的解题方案(洛谷P8767)

【蓝桥杯国赛A组】冰山体积计算:动态规划与map统计的解题方案(洛谷P8767)

一、题目解读本题为2021年蓝桥杯国赛A组题目“冰山”(洛谷P8767),要求处理冰山在融化与新生成过程中的体积变化。每日存在两种操作:冰山体积按固定值x融化(体积不足x的部分视为完全融化),以及新增...

【2020蓝桥杯国赛C组】补给题解析:从Floyd到动态规划的高效解法

【2020蓝桥杯国赛C组】补给题解析:从Floyd到动态规划的高效解法

一、题目解读2020年蓝桥杯国赛C组“补给”题目要求:给定n个村庄坐标及最大补给距离D,需判断是否所有村庄均可从总部(村庄0)直接或间接到达,并计算访问所有村庄的最小路径(即旅行商问题TSP)。题目核...

力扣面试题02.05链表相加:虚拟头节点+迭代解法的详细解析

力扣面试题02.05链表相加:虚拟头节点+迭代解法的详细解析

一、题目解读力扣面试题02.05要求将两个链表表示的整数相加,每个节点存储一位数字(逆序),结果同样以链表形式返回。例如,链表1为7→2→4,链表2为5→6→3,相加结果应为2→9→8→7。题目难点在...

发表评论

访客

看不清,换一张

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