高精度_加减乘除(理论+模板+例题)

news2024/11/26 0:48:09

👂 Rush E (Impossible Version) - Sheet Music Boss - 单曲 - 网易云音乐

👂 My Favorite Things - 羊毛とおはな - 单曲 - 网易云音乐

目录

🌼前言

🌼理论

🌼理论结合题目

🏆1088: 大整数加法

🏆1089: 大整数减法

🏆1090: 大整数乘法

🏆1091: 大整数除法(一)

🏆P1480 A/B Problem

🏆1092: 大整数除法(二)

🌼总结


🌼前言

跟着博客完整看一遍,AC一遍所有题,你就勉强学会高精度了(ง •_•)

-->  最近在学《算法训练营入门篇》

-->  需要结合洛谷官方题单

-->  洛谷官方题单,贪心题型里,遇到了一道涉及高精度的题“国王的游戏”

-->  所以花几个小时,系统学一下高精度

步骤

1,理论 + 解析 + 模板

结合   1篇Oi-Wiki + 4个B站视频

2,刷题

New Oj五道题

看了下理论,加很简单,减需要处理下小 - 大,乘需要找规律,除则分2类题型分别找规律

建议看理论时,自己在草稿纸 / 键盘模拟一遍竖式,助于理解

🌼理论

帮大家筛选了一些好的博客和视频(看一遍就懂的那种)

视频

加,减,乘

一个视频带你了解高精度计算!再也不用担心数据溢出了!_哔哩哔哩_bilibili

高精度乘法_哔哩哔哩_bilibili

除1

高精度除法(高精度除以低精度)_哔哩哔哩_bilibili

除2

高精度除法(高精度除以高精度)_哔哩哔哩_bilibili

博客

高精度计算 - OI Wiki (oi-wiki.org)

建议先1.5倍速看完视频,再看博客

高精度计算,也称大整数计算,大整数 加,减,乘,除(乘 / 除 还分高精度与低精度混搭)

高精度的本质:

利用字符串模拟数字,再运用类似数学中,竖式的形式,一位一位地计算

思路

截图来源于B站  麦克老实讲算法 

1,存储:字符串转整型,输入数组(下标0和1有所区别)

2,分类:

(1)加减硬算

(2)乘法找规律

两层for循环遍历

(3)除法1:高精 / 低精,逐位试商

(4)除法2:高精 / 高精,减法模拟除法

高精 / 高精是5种高精度里,最难的,建议1.5倍速看2遍视频,结合截图和AC代码中的注释理解,然后自己一定要模拟几次截图,或者跟着视频模拟一遍

3,补充:去除前导0

一层for加个if判断即可去除前导0

低精度可以理解为int, long long, double....可以直接存储

高精度就是长到无法直接用这些类型存储的数字,比如👇

1827391827382739156134576134876519645871654387613745773333333333333333333746573648576384765872687263857624856827349658726583746582736458726348756283476582364587263487562837465872634856238475682376458726348765...

🌼理论结合题目

截图来源于B站  麦克老实讲算法

🏆1088: 大整数加法

P1088 - 大整数加法 - New Online Judge (ecustacm.cn)

看注释

AC  代码

#include<iostream>
using namespace std;
int a[1010], b[1010], c[1010];

int main()
{
    string s1, s2;
    cin>>s1>>s2; //作为字符串输入
    int len1 = s1.length(), len2 = s2.length();
    //转整型存入数组
    for(int i = 0; i < len1; ++i)
        a[i] = s1[len1 - i - 1] - '0'; //从小开始存
    for(int i = 0; i < len2; ++i)
        b[i] = s2[len2 - i - 1] - '0';
    //得到较大数的长度
    int len = max(len1, len2);
    //按位相加
    for(int i = 0; i < len; ++i) {
        c[i] += a[i] + b[i]; //注意 +=
        c[i + 1] += c[i] / 10;
        c[i] %= 10;
    }
    //输出
    if(c[len] != 0) len++; //相加后长度增加
    for(int i = len - 1; i >= 0; --i)
        cout<<c[i];

    return 0;
}
3297419374129481729874319287439812312957616548765481364587168576184658164582734
53827459827439875238745987544873875948729347592473592347592374598273945723
3297473201589309169749558033427357186833565278113073838179516168559256438528457

🏆1089: 大整数减法

P1089 - 大整数减法 - New Online Judge (ecustacm.cn)

第一次敲,AC  90%,有个很坑的地方,一开始以为是String类字符串的比较出问题了

就是2 > 100,因为它会按顺序比较,2 > 1所以 2 > 100,只需加个len的比较就行

我的问题是,当100 - 100会没有输出,最后补充个相等时,输出的0就行

AC  代码

#include<iostream>
using namespace std;
int a[1010], b[1010], c[1010];

void read(int a[], string s)
{
    int len = s.length();
    for(int i = 0; i < len; ++i)
        a[i] = s[len - i - 1] - '0'; //从低位读入
}

int main()
{
    string s1, s2;
    int len1, len2;
    cin>>s1>>s2; //作为字符串输入
    len1 = s1.length(), len2 = s2.length();
    if(len1 < len2 || (s1 < s2 && len1 == len2)) {//小的 - 大的
        cout<<"-"; //提前输出个负号
        len1 = s2.length(), len2 = s1.length();
        //读入数组
        read(a, s2); //大的读入a[]
        read(b, s1); //小的读入b[]
    }
    else {
        //读入数组
        read(a, s1); //大的读入a[]
        read(b, s2); //小的读入b[]
    }
    //执行上述操作后, a[]的数更大, len1更大
    //按位相减
    for(int i = 0; i < len1; ++i) {
        c[i] += a[i] - b[i]; //注意+=
        if(c[i] < 0) { //借位
            c[i + 1] -= 1;
            c[i] += 10;
        }
    }
    //排除前导0
    int k;
    for(k = len1 - 1; k >= 0; --k)
        if(c[k] != 0) break;
    //输出
    for(int i = k; i >= 0; --i)
        cout<<c[i];
    //补充一个很坑的点
    if(len1 == len2 && s1 == s2)
        cout<<0;
    return 0;
}

几组输出

100
100
0

5858
5959
-101

3535
34341
-30806

🏆1090: 大整数乘法

P1090 - 大整数乘法 - New Online Judge (ecustacm.cn)

上面乘法规律的图中,是c[i + j - 1] += a[i] * b[j];

此时下标0开始会越界,出现-1,所以下标从1开始输入数组

,此时c[1 + 1 - 1] += a[1] * b[1],就不受影响

下标从1开始后,相应的s1, s2, a[], b[], c[]的下标也要全部改

AC  代码

第一次敲完,又是90%,跟减法一样的错误,漏了为0的情况

#include<iostream>
using namespace std;
int a[1010], b[1010], c[2010]; //2010防止溢出

int main()
{
    string s1, s2;
    cin>>s1>>s2;
    int n = s1.length(), m = s2.length(); //字符串长度
    //读入数组
    for(int i = 1; i <= n; ++i)
        a[i] = s1[n - i] - '0'; //最低位读入数组前面
    for(int i = 1; i <= m; ++i)
        b[i] = s2[m - i] - '0';
    //按位相乘
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j) {
            c[i + j - 1] += a[i] * b[j];
            //每次乘完后进位
            c[i + j] += c[i + j - 1] / 10;
            c[i + j - 1] %= 10;
        }
    //排除前导0
    int k;
    for(k = n + m + 1; k >= 1; --k)
        if(c[k] != 0) break;
    //逆序, 大到小输出
    for(int i = k; i >= 1; --i)
        cout<<c[i];
    //补充存在一个是0的情况
    if((n == 1 && s1[0] == '0') || (m == 1 && s2[0] == '0'))
        cout<<0;
    return 0;
}

几个测试

123809128390 0
0

19 6
114

381247923749174398123947128347912374918237 932894898437192874398127394871
355664243105376703364270700582783731140893607514391377000718338438162427

🏆1091: 大整数除法(一)

P1091 - 大整数除法(一) - New Online Judge (ecustacm.cn)

第一类高精度除法:高精 / 低精

注意判断被除数 < 除数的情况

敲代码时,可在草稿纸写出竖式,逐步比对,除数b,余数x,c[]数组的关系

比如4567 / 123👇

第一次AC  40%...还是加了被除 < 除数的判断

于是我去洛谷找了个类似的题

🏆P1480 A/B Problem

P1480 A/B Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

当输入下列数据没有输出9  0

9000000000
1000000000
0
410065408

for(int i = 0; i < n; ++i) { //c[]位数和高精度数组a[]一样
    c[i] = (x * 10 + a[i]) / b; //商
    x = (x * 10 + a[i]) % b; //余数
}

分析

当 i == 0, x = 9 * 10^0, c[0] = 0 ...

当 i == 8, x = 9 * 10^8, c[8] = 0

当 i == 9, x = 9 * 10^9已经越界,改为long long洛谷就能过,然后New Oj也过了(无语。。。

原来只是个long long的BUG,找了半小时)

long long b, x = 0; //b为除数, x为余数

洛谷AC  代码

#include<iostream>
using namespace std;
int a[5010], c[5010]; //c[]为答案数组

int main()
{
    string s;
    //注意开long long!!!
    long long b, x = 0; //b为除数, x为余数
    cin>>s>>b;
    int n = s.length(); //字符串长度
    //读入数组
    for(int i = 0; i < n; ++i)
        a[i] = s[i] - '0'; //最高位读入数组前面
    //逐位试商法
    for(int i = 0; i < n; ++i) { //c[]位数和高精度数组a[]一样
        c[i] = (x * 10 + a[i]) / b; //商
        x = (x * 10 + a[i]) % b; //余数
    }
    //去除前导0
    int k;
    for(k = 0; k < n; ++k)
        if(c[k] != 0) break;
    //输出
    for(int i = k; i < n; ++i)
        cout<<c[i]; //商
    //被除数 < 除数的补充
    if(k == n && !c[k - 1])
        cout<<0; //商为0
    //cout<<endl<<x; //余数

    return 0;
}

AC  代码

#include<iostream>
using namespace std;
int a[5010], c[5010]; //c[]为答案数组

int main()
{
    string s;
    //注意开long long!!!否则最后x会越界
    long long b, x = 0; //b为除数, x为余数
    cin>>s>>b;
    int n = s.length(); //字符串长度
    //读入数组
    for(int i = 0; i < n; ++i)
        a[i] = s[i] - '0'; //最高位读入数组前面
    //逐位试商法
    for(int i = 0; i < n; ++i) { //c[]位数和高精度数组a[]一样
        c[i] = (x * 10 + a[i]) / b; //商
        x = (x * 10 + a[i]) % b; //余数
    }
    //去除前导0
    int k;
    for(k = 0; k < n; ++k)
        if(c[k] != 0) break;
    //输出
    for(int i = k; i < n; ++i)
        cout<<c[i]; //商
    //被除数 < 除数的补充
    if(k == n && !c[k - 1])
        cout<<0; //商为0
    cout<<endl<<x; //余数

    return 0;
}

🏆1092: 大整数除法(二)

P1092 - 大整数除法(二) - New Online Judge (ecustacm.cn)

减法模拟除法

需要注意的是,减法,需要高精度减法来实现

同时,由于是高精度减法,需要逆序读入数组,即低位放前面

因为代码较复杂,注意死循环的问题,比如 

for(int i = len2 - 1; i >= 0; ++i) {

}

犯了习惯性的问题,有时没有输出,不妨看看是不是这个原因

同时,将每个数组的长度保存在a[0], b[0], bb[0], c[0]的位置

那么下标都从1开始

第一次写崩了,思路清晰后重敲了遍

AC  代码

注释占了13行,确实有点长,但思路很清晰

#include<iostream>
#include<cstring> //memset()
using namespace std;

int a[1010], b[1010], c[1010], tmp[1010]; //a被除, b除数, c商

void cpy(int x[], int y[], int n) //x[]左移n位拷贝到y[]
{
    for(int i = 1; i <= x[0]; ++i) y[i + n] = x[i];
    y[0] = x[0] + n; //y[0]保存该数组大小
}

int compare(int a[], int b[]) //判断是否可以继续减
{
    if(a[0] > b[0]) return 1; //a > b, 可以继续减
    if(a[0] < b[0]) return -1; //a < b, 不可以继续, 下次循环左移少1位
    for(int i = a[0]; i >= 1; --i) { //从高位开始比较
        if(a[i] > b[i]) return 1;
        if(a[i] < b[i]) return -1;
    }
    return 0; //相等, 可以再减1次
}

void sub(int a[], int b[]) //高精度减法, 按位相减
{
    for(int i = 1; i <= a[0]; ++i) {//低位开始相减, 不足就借位
        if(a[i] < b[i]) {
            a[i + 1]--; //借位
            a[i] += 10;
        }
        a[i] -= b[i];
    }
    while(a[a[0]] == 0 && a[0] > 0) a[0]--; //更新a[0], 删除前导0
}

int main()
{
    string s1, s2;
    cin>>s1>>s2;
    //a[0]被除数长度, b[0]除数, c[0]商最大长度
    a[0] = s1.size(), b[0] = s2.size(), c[0] = a[0] - b[0] + 1;
    //分类讨论: 如果被除数更小
    //低位存入数组开头
    for(int i = 1; i <= a[0]; ++i) a[i] = s1[a[0] - i] - '0';
    for(int i = 1; i <= b[0]; ++i) b[i] = s2[b[0] - i] - '0';
    if(a[0] < b[0] || (a[0] == b[0] && s1 < s2))
        cout<<0; //商为0
    else {
        //减法模拟除法
        for(int i = c[0]; i >= 1; --i) {
            memset(tmp, 0, sizeof(tmp)); //恢复为0
            cpy(b, tmp, i - 1); //b[]左移"商 - 1"位, 拷贝到tmp[]
            while(compare(a, tmp) >= 0) { //可以继续减
                c[i]++; //该位的商 +1
                sub(a, tmp); //高精度减法, a[]上按位减去tmp[]
            }
        }
        //去除前导0
        int k;
        for(k = c[0]; k >= 1; --k)
            if(c[k] != 0) break;
        //高位开始输出商
        for(int i = k; i >= 1; --i)
            cout<<c[i]; //商
    }
    //高位开始输出余数a[]
    cout<<endl;
    for(int i = a[0]; i >= 1; --i)
        cout<<a[i];

    return 0;
}

🌼总结

不容易的,编码能力还是挺差,不过比之半年前好了一点点,起码debug的熟练度得到提升

慢慢来,呗,劳逸结合的前提下,尽可能的学习

少点睡到12点才起床

目前每周还是会有4天睡到12点才起,得改改懒惰的性子了

看到这里的朋友,也要上进点~

补充

当然,还有 压位高精度Karatsuba 乘法 

想要进阶的可以去Oi-Wiki学学

花了整整一天才写完这个博客,慢慢加油吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/525577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android Jetpack之Room数据库的使用(Kotlin+Room)

作者&#xff1a;舒呐 一、基本介绍 Room 持久性库在 SQLite 上提供了一个抽象层&#xff0c;以便在充分利用 SQLite 的强大功能的同时&#xff0c;能够流畅地访问数据库。具体来说&#xff0c;Room 具有以下优势&#xff1a; 针对 SQL 查询的编译时验证。可最大限度减少重复…

django ORM框架(操作数据库)

一、ORM框架介绍 ORM框架&#xff0c;把类和数据进行映射&#xff0c;通过类和对象操作它对应表格中的数据&#xff0c;进行增删改查&#xff08;CRUD) ORM框架中 数据库&#xff1a;需要提前手动创建数据库 数据表&#xff1a;与OMR框架中的模型类对应 字段&#xff1a;模…

阿里云,又瘫了!

大家好&#xff0c;我是老杨。 不知道你对前段时间&#xff0c;阿里云瘫痪的事情有印象不&#xff1f; 12月18号&#xff0c;阿里云发生了大规模服务中断的事情——主要是阿里云香港Region可用区C发生大规模服务中断事件。 中断也不是第一次了&#xff0c;但引起我注意的是&…

面向对象技术

面向对象技术 面向对象基础 面向对象基本概念 面向对象分析 面向对线设计 面向对象测试 UML 事务 关系 图 设计模式 创建型设计模式 结构型设计模式 行为型设计模式 面向对象基本概念 面向对象基本概念 达成目标具体需要做哪些事情。 对象 : 基本的运行实体,为类的实…

Vector - CAPL - CANoe硬件配置函数 - 05

目录 resetCan -- 重置CAN控制器 代码示例 ResetCanEx -- 重置CAN控制器的特定CAN通道 代码示例 ScanBaudrateActive -- 特定通道设置波特率 ScanBaudratePassive -- 开始扫描并检测给定通道上的波特率 resetCan -- 重置CAN控制器 功能&#xff1a;重置CAN控制器&#xf…

(2020)End-to-end Neural Coreference Resolution论文笔记

2020End-to-end Neural Coreference Resolution论文笔记 Abstract1 Introduction2 Related Work3 Task4 Model4.1 Scoring Architecture4.2 Span Representations5 Inference6 Learning7 Experiments7.1 HyperparametersWord representationsHidden dimensionsFeature encoding…

学习HCIP的day.06

十一、OSFP扩展知识点 1、关于OSPF状态机的问题 &#xff08;1&#xff09;在MA网络中&#xff08;要进行DR/BDR选举&#xff09;存在7种状态机&#xff0c;init是路由器A收到邻居B的hello包&#xff0c;但该hello包中没有A的RID&#xff1b; &#xff08;2&#xff09;在点到…

汽车EEA架构演进以及域控制器发展介绍

1、重要名词解析 &#xff08;1&#xff09;SDV&#xff1a;软件定义汽车&#xff1b; &#xff08;2&#xff09;SOA &#xff1a;一种 C/S 架构的软件设计方法&#xff1b; &#xff08;3&#xff09;OTA&#xff1a;空中下载技术&#xff08;Over-the-Air Technology&#x…

【MySql】数据库事务

事务 事务事务的操作事务并发处理可能出现的问题隔离级别MVCC&#xff1a;多版本并发控制 事务 事物本质上指一条 sql 语句或一组 sql 组合 事务的特性&#xff1a;ACID 1、原子性&#xff1a;一个事务&#xff0c;要么一次性完成&#xff0c;要么就不做 2、一致性&#xff1…

STM32驱动超声波+OLED显示,并上传数据到云端(ONENET)

本文将介绍如何使用STM32F103C8T6单片机和HC-SR04超声波测距模块来实现测距功能&#xff0c;并通过0.96寸OLED屏幕显示测距结果。 首先&#xff0c;我们需要了解一下HC-SR04超声波测距模块的工作原理。该模块通过发送超声波脉冲并接收回波信号的时间来计算物体与模块之间的距离…

C++ STL 标准模板库介绍与入门

目录 1、概述 1.1、C 标准库 1.2、Boost库 2、STL 版本 2.1、HP 原始版本 2.2、P. J. 实现版本 2.3、RW 实现版本 2.4、SGI 实现版本 2.5、STLport 实现版本 3、STL 的六大组件 3.1、STL 六大组件构成 3.2、六大组件的交互关系 4、STL 的重要性 5、总结 VC常用功…

java spring MVC之RESTful快速开发

我这里有个一springboot项目 我在启动类同目录下创建了一个目录 目录名叫 controller 里面有一个UserController diam结构是这样的 package com.example.threshold.controller;import com.example.threshold.user; import org.springframework.stereotype.Controller; import…

平衡二叉树理论详解

文章目录 基本概念平衡二叉树插入结点LL&#xff08;左单旋&#xff09;RR&#xff08;右单旋&#xff09;LR&#xff08;左右旋&#xff09;RL&#xff08;右左旋&#xff09; 示例插入推导过程 基本概念 平衡二叉树是一棵空树或它的左右两个子树的高度差的绝对值不超过1&…

Maven ( 二 ) 项目应用

4.资源管理 4.0.pom.xml Maven的pom.xml是一个项目对象模型(Project Object Model)&#xff0c;它是Maven项目的构建文件。它描述了一个项目的基本信息&#xff0c;包括项目依赖、插件、仓库等信息。 下面是一个简单的pom.xml示例&#xff1a; <project xmlns"http…

深度学习用于医学预后-第二课第三周4-7节-关于事件的时间数据,认识处理删失数据

在本课中&#xff0c;我们将讨论生存数据。为了能够对生存进行建模&#xff0c;我们需要能够以我们可以处理的形式表示数据。 主要的挑战是删失数据&#xff0c;这是一种特殊形式的缺失数据。我们接下来将要研究这一点。 在这节课中&#xff0c;我们将谈论生存数据和删失。 …

LeetCode 96 不同的二叉搜索树

题目&#xff1a; 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5 示例 2&#xff1a; 输入&#xff1a;n 1 …

第七章:C语言的操作符

说起操作符大家都不陌生&#xff0c;从我们最初的 - c * / 加减乘除&#xff0c;到更加深奥的操作符&#xff0c;而今天我要有完整的系统来理清楚C语言的操作符到底有什么&#xff0c;和它们相关的用法&#xff0c;话不多说&#xff0c;直接走进今天的主题----C语言的操…

保护个人隐私和数据安全的方法与策略

引言 随着信息技术的普及和发展&#xff0c;我们享受到了便捷的互联网服务&#xff0c;但与此同时&#xff0c;个人隐私和数据安全问题也日益受到威胁。在这个所谓的"裸奔"时代&#xff0c;网络攻击、数据泄露和隐私侵犯已经成为常态。然而&#xff0c;我们并不无助…

sysfs文件系统

sysfs系统介绍 sysfs系统sysfs系统是什么&#xff1f;koject的内核对象模型基础kobject结构体定义kest bus如何管理driver和devicebus_type 结构体 小知识什么是挂载mount命令 &#x1f4cc;————本章重点————&#x1f4cc; &#x1f517;了解sysfs系统概念; &#x1f5…

布谷鸟hash算法的并行化实现(一)

由于本人最近在写一个项目&#xff0c;为了实现数据查找以及数据修改部分的快速操作&#xff0c;所以采用hash对数据进行存储&#xff0c;而在此过程中接触到了布谷鸟hash&#xff0c;觉得这个hash算法还是很有意思并且高效&#xff0c;所以想着进行一些记录&#xff0c;本系列…