当前位置:首页 > 提高组 > 洛谷P1080题(2012年NOIP提高组):国王游戏的高精度计算解法

洛谷P1080题(2012年NOIP提高组):国王游戏的高精度计算解法

4小时前

洛谷P1080题(2012年NOIP提高组):国王游戏的高精度计算解法 高精度计算 运算符重载 NOIP 提高组 第1张

一、题目解读

洛谷P1080题要求解决一个关于大臣与国王乘积比较的问题:给定国王和n位大臣的左右能力值,需统计有多少大臣的左右能力乘积小于国王的乘积。题目核心在于处理大数乘积计算与高效比较,需避免整数溢出,因此高精度算法成为关键。

二、解题思路

1. 高精度整数处理:自定义BigInt类,通过vector存储数字逆序各位,支持乘法(逐位相乘+进位处理)与除法(模拟竖式除法),解决大数运算问题。

2. Minister结构设计:定义Minister包含左右能力值,重载<运算符为乘积比较,便于后续排序或筛选。

3. 核心逻辑:遍历大臣,计算其乘积并与国王比较,利用高精度运算确保准确性。

三、解题步骤

1. 输入与初始化:读取国王能力值及大臣数量n,构建Minister数组存储大臣数据。

2. 高精度乘积计算:利用BigInt类的乘法运算,计算每位大臣的左右乘积(若直接使用内置类型可能溢出)。

3. 比较与计数:通过重载的<运算符(乘积比较)判断大臣乘积是否小于国王,累加符合条件的大臣数量。

4. 优化处理:代码中已包含高精度除法(虽未直接用于本题,但为扩展性设计),实际比较仅依赖乘法结果。

四、代码与注释

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

// 高精度整数类
struct BigInt {
    vector<int> digits;
    
    BigInt(int num = 0) {
        while (num) {
            digits.push_back(num % 10);
            num /= 10;
        }
    }
    
    BigInt& operator*=(int num) {
        int carry = 0;
        for (int i = 0; i < digits.size(); ++i) {
            int product = digits[i] * num + carry;
            digits[i] = product % 10;
            carry = product / 10;
        }
        while (carry) {
            digits.push_back(carry % 10);
            carry /= 10;
        }
        return *this;
    }
    
    BigInt operator/(int num) const {
        BigInt res;
        res.digits.resize(digits.size());
        int remainder = 0;
        for (int i = digits.size() - 1; i >= 0; --i) {
            int current = remainder * 10 + digits[i];
            res.digits[i] = current / num;
            remainder = current % num;
        }
        while (res.digits.size() > 1 && res.digits.back() == 0) {
            res.digits.pop_back();
        }
        return res;
    }
    
    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 false;
    }
};

struct Minister {
    int left, right;
    bool operator<(const Minister& other) const {
        return left * right < other.left * other.right;
    }
};

int main() {
    int n;
    cin >> n;
    Minister king;
    cin >> king.left >> king.right;
    
    vector<Minister> ministers(n);
    for (int i = 0; i < n; ++i) {
        cin >> ministers[i].left >> ministers[i].right;
    }
    
    // 按左右手乘积排序
    sort(ministers.begin(), ministers.end());
    
    BigInt product(king.left);
    BigInt max_reward(0);
    
    for (int i = 0; i < n; ++i) {
        BigInt reward = product / ministers[i].right;
        if (max_reward < reward) {
            max_reward = reward;
        }
        product *= ministers[i].left;
    }
    
    // 输出最大奖励
    for (int i = max_reward.digits.size() - 1; i >= 0; --i) {
        cout << max_reward.digits[i];
    }
    cout << endl;
    
    return 0;
}

五、总结

本解法通过高精度整数类与运算符重载,巧妙解决大数乘积比较问题。核心在于:

1. 用vector动态存储数字位数,避免固定长度限制;

2. 乘法算法的进位处理确保正确性;

3. 自定义比较运算符简化逻辑,提升代码可读性。

该思路适用于类似大数运算场景,为算法竞赛中处理高精度问题的典型范例。

原创内容 转载请注明出处

分享给朋友:

相关文章

手把手教你实现简易C++字符串类:从代码注释到实战应用

一、简介和特点本文将带领新手小白一步步了解如何手动实现一个简易的C++字符串类。这类自定义字符串类具备基本功能,如存储字符、获取长度、赋值、比较、拼接等操作。通过手搓代码,读者能深入理解C++中字符串...

2018年NOIP货币系统解题报告(洛谷P5020):动态规划与完全背包的巧妙应用

2018年NOIP货币系统解题报告(洛谷P5020):动态规划与完全背包的巧妙应用

一、题目解读2018年NOIP货币系统问题(洛谷P5020)要求给定一组货币面额,判断是否存在一种组合方式,使得所有不超过最大面额的金额都能被表示。例如,若面额集合为{1,3,5},则金额1~8均可被...

洛谷P1033题(2002年NOIP提高组):基于物理公式用C++解决自由落体

洛谷P1033题(2002年NOIP提高组):基于物理公式用C++解决自由落体

一、题目解读洛谷P1033题要求计算小车在限定时间内能接住多少自由落体的小球。输入参数包括天花板高度H、小车初始位置S1、速度V、长度L、高度K及小球数量n。题目需结合物理运动学公式,判断每个小球的初...

发表评论

访客

看不清,换一张

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