C++:第十五讲高精度算法

每日C++知识

 system("color xx);是改变字体及背景颜色,前一个x代表一个数字,可以改变背景颜色,后一个x代表一个数字,可以改变字体颜色 ,但都是根据颜色表来的。

记住:要加头文件:#include<windows.h>

颜色对照表: 
0 = 黑色
1 = 蓝色
2 = 绿色
3 = 湖蓝色
4 = 红色
5 = 紫色
6 = 黄色
7 = 白色
8 = 灰色
9 = 亮蓝色
A = 亮绿色
B = 亮湖蓝色
C = 亮红色
D = 亮紫色
E = 亮黄色
F = 亮白色 

例子:

#include<bits/stdc++.h>
#include<windows.h> 
using namespace std;
int main(){system("color 01");cout<<"1234567890"; return 0;
}

输出结果:

 

高精度简介

在C++中当你用int、long long,甚至是unsigned long long 都无法处理的超级巨大数字,你会感到无比痛苦甚至到绝望,那么我们此时就只有一种方法了——高精度算法。我们可以利用程序设计的方法去实现这样的高精度计算。介绍常用的几种高精度计算的方法。本文主要实现的是自然数范围内做运算的 加法、减法、乘法、除法 四种基本高精度运算。

高精度(High Precision)是一种在计算机编程中用于表示和操作大数的技术。在C++中,可以使用高精度思想来处理大数,例如质数、因数分解等。

(1)高精度加法,所用到的算法很简单,其实就是我们小学所学的加法“竖式”计算。将两个加数的对应数位对齐,也就是说个位对个位、十位对十位、百位对百位,对应的数位进行加法操作,有进位的要进位。

(2)高精度加法要将两个加数按对应的位数一位一位地处理,所以在实践中,将两个加数分别用两个数组进行存储,问题就会变得简单。

(3)之前我们已经说过,C++中最大的整数是long long型,最大位数是20位。所以对于10000位的正整数,我们输入的数据类型应该是一个字符串,也就是string型的数据。

例题1洛谷P1303 A*B Problem

题目描述

给出两个非负整数,求它们的乘积。

输入格式

输入共两行,每行一个非负整数。

输出格式

输出一个非负整数表示乘积。

输入输出样例

输入 #1

1
2

输出 #1

2

说明/提示

每个非负整数不超过10的2000次方

解题思路

在讲这道题之前,我有必要先从高精度加/减法来引入一下。

高精度加减法最重要的是什么?当然是对齐数位了!那么,为了达到这一点,我们不惜要先将输入倒序存储,高精乘也是这样。下面,拿一张表格来示意一下高精度加法的运算过程:

20056
+19023
=39079

那么高精乘呢?他们也需要判定位置关系,只不过关系表达式用坐标表示是这样的:a[i]*b[j]==c[i,j]//乘数 * 乘数=乘积。

AC

#include<bits/stdc++.h>
using namespace std;
char a1[10001],b1[10001];
int a[10001],b[10001],i,x,len,j,c[10001];
int main ()
{cin>>a1>>b1;int lena=strlen(a1);int lenb=strlen(b1);for(i=1;i<=lena;i++)a[i]=a1[lena-i]-'0';for(i=1;i<=lenb;i++)b[i]=b1[lenb-i]-'0';for(i=1;i<=lenb;i++)for(j=1;j<=lena;j++)c[i+j-1]+=a[j]*b[i];for(i=1;i<lena+lenb;i++)if(c[i]>9){c[i+1]+=c[i]/10;c[i]%=10;}len=lena+lenb;while(c[len]==0&&len>1)len--;for(i=len;i>=1;i--)cout<<c[i];return 0; 
}

例题2洛谷P1480 A/B Problem

题目描述

输入两个整数 a,b,输出它们的商。

输入格式

两行,第一行是被除数,第二行是除数。

输出格式

一行,商的整数部分。

输入输出样例

输入 #1

10
2

输出 #1

5

说明/提示

0≤a≤10的5000次方,1≤b≤10的9次方。

解题思路

这是一道高精除低精模板题。

模拟竖式被除数的每一位加上余数除以被除数并更新余数的过程即可。

不过要注意一下:在数 a 后面拼上一位数 b 是 10a+b。

自己推一下竖式就可以理解了。

记得最后要去除前导零。

AC

#include <iostream>
using namespace std;
string a, res;
long b;
int main() {cin >> a >> b;long t = 0;for (int i = 0; i < a.size(); i++) {res.push_back((t * 10 + a[i] - '0') / b + '0');t = (t * 10 + a[i] - '0') % b;}int i = 0;while (i + 1 < res.size() && res[i] == '0') i++;cout << res.substr(i) << endl;
}

例题3洛谷P1601 A+B Problem

题目描述

高精度加法,相当于 a+b problem,不用考虑负数

输入格式

分两行输入。a,b≤10的500次方。

输出格式

输出只有一行,代表 a+b 的值。

输入输出样例

输入 #1

1
1

输出 #1

2

输入 #2

1001
9099

输出 #2

10100

说明/提示

20% 的测试数据,0≤a,b≤10的9次方;

40% 的测试数据,0≤a,b≤10的18次方。

解题思路

A+B高精度版其实是一道模板题,在很多领域都有用处。

高精度算法,属于处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。

AC

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
void add(char a[], char b[])
{//获取数组长度int alen = strlen(a), blen = strlen(b), t = 0, i,len;// 翻转数组,为了低位对齐reverse(a,a+alen);reverse(b,b+blen);// 存放·结果int c[502]={0};// 取较短的位len = (alen < blen) ? alen : blen;// 对应位相加for (i = 0; i <len; i++){c[i]=((a[i]+b[i]-'0'-'0')+t);// t代表进位t=c[i]/10;c[i]=c[i]%10;}// 剩余位处理while (i<alen){c[i]=t+(a[i]-'0');t=c[i]/10;c[i]=c[i]%10;i++;}while (i<blen){c[i]=t+(b[i]-'0');t=c[i]/10;c[i]=c[i]%10;i++;}// 最高位进位if(t!=0){c[i]=t;i++;}// 输出for(i=i-1; i >= 0; i--) printf("%d", c[i]);
}
int main()
{char a[502]={0}, b[502]={0};scanf("%s %s", a, b);add(a,b);return 0;
}

课后练习P1080 [NOIP2012 提高组] 国王游戏

题目描述

恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。

输入格式

第一行包含一个整数 n,表示大臣的人数。

第二行包含两个整数 a 和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。

接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出格式

一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

输入输出样例

输入 #1

3
1 1
2 3
7 4
4 6 

输出 #1

2

说明/提示

【输入输出样例说明】

按 1、2、3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按 1、3、2 这样排列队伍,获得奖赏最多的大臣所获得金币数为2;

按 2、1、3 这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按2、3、1这样排列队伍,获得奖赏最多的大臣所获得金币数为 9;

按 3、1、2这样排列队伍,获得奖赏最多的大臣所获得金币数为 2;

按3、2、1 这样排列队伍,获得奖赏最多的大臣所获得金币数为 9。

因此,奖赏最多的大臣最少获得 2个金币,答案输出2。

【数据范围】

对于 20%的数据,有 1≤n≤10,0<a,b<8;

对于 40%的数据,有1≤n≤20,0<a,b<8;

对于 60%的数据,有 1≤n≤100;

对于 60%的数据,保证答案不超过 10的9次方;

对于 100%的数据,有 1≤n≤1,000,0<a,b<10000。

解题思路

其实懂了思想还是挺简单的,朴素的高精度乘法和高精度除法,但难想到的还是如何一开始给他们排序,于是冥思苦想,终于发现了如何排序(好吧,借鉴了别人的想法),便是按a*b排序。

为什么呢?我简单说明一下,假设前面几个人都排好了,我们要如何证明最后两个人谁排前面会对答案影响小一点呢?也就是贡献得尽量小一点,设前几个人a的乘积为x,那么这两个人(a1,b1)和(a2,b2)谁排前一个结果就为x*a1/b2和x*a2/b1,将他们做下比较,易得出当a1*b1<a2*b2时(a1,b1)排在前面更好【可以在草稿纸上列下不等式算下,不难得出】,然后就简单了!

AC

#include<bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
string hmul(string a,string  b){int c[500005];memset(c,0,sizeof c);int x[a.size()],y[b.size()];memset(x,0,sizeof x);memset(y,0,sizeof y);for(unsigned int i=0;i<a.size();i++)x[a.size()-1-i]=a[i]-'0';for(unsigned int i=0;i<b.size();i++)y[b.size()-i-1]=b[i]-'0';for(unsigned int i=0;i<a.size();i++){for(unsigned j=0;j<b.size();j++){c[i+j]+=x[i]*y[j];}}for(unsigned int i=0;i<a.size()+b.size();i++){if(c[i]>=10){c[i+1]+=c[i]/10;c[i]%=10;}}string ci;bool p=1;for(int i=a.size()+b.size()-1;i>=0;i--){if(c[i]==0&&p) continue;else{p=0;ci+=c[i]+'0';}}return ci;
}
string hdiv(string a,int b){int x[50005];int y[50005];memset(x,0,sizeof(x));memset(y,0,sizeof(y));for(unsigned int i=0;i<a.size();i++){x[i+1]=a[i]-'0';}int yu=0;for(unsigned int i=1;i<=a.size();i++){y[i]=(yu*10+x[i])/b;yu=(yu*10+x[i])%b;}int kk=1;while(y[kk]==0&&kk<a.size()) kk++;string aa;for(unsigned int i=kk;i<=a.size();i++){aa+=y[i]+'0';}return aa;
}
string smx(string a,string b){if(a.size()!=b.size()) return a.size()>b.size()?a:b;return a>b?a:b;
}
string tur_str(int num){string str;while(num){str+=num%10+'0';num/=10;}reverse(str.begin(),str.end());return str;
}
int n;
struct aa{int l,r;
}a[100005];
bool cmp(aa a,aa b){return (a.l*a.r)<(b.l*b.r);
}
int main(){cin>>n;cin>>a[0].l>>a[0].r;for(int i=1;i<=n;i++) cin>>a[i].l>>a[i].r;sort(a+1,a+n+1,cmp);string ans="0";string xx=tur_str(a[0].l);for(int i=1;i<=n;i++){ans=smx(ans,hdiv(xx,a[i].r));//cout<<"ans=="<<ans<<endl;xx=hmul(xx,tur_str(a[i].l));}cout<<ans<<endl;return 0;
}

结尾

希望大家多多关注!!!

本篇文章共5996字,如果你能支持一下我,我十分感谢!!!

如果有人想在洛谷上做题,可以点下方链接:

https://www.luogu.com.cn/

如果你喜欢或想了解一下其他的算法,可以看看以下这些:

题目详解系列(部分):

【万题详解】洛谷P1252 马拉松接力赛-CSDN博客

【万题详解】洛谷P1359 租用游艇-CSDN博客

【百题详解】洛谷P8508 做不完的作业-CSDN博客

【万题详解1】洛谷P1230 智力大冲浪-CSDN博客

【全网首发】洛谷贪心题解集合-CSDN博客

洛谷二分题集(3题)-CSDN博客

游戏系列:

C++:史上最坑小游戏-CSDN博客

 C++:自创小游戏-CSDN博客

C++:下雪-CSDN博客

C++讲解系列(算法):

C++:第十二讲DFS深搜(二)_c++匿名函数dfs-CSDN博客

 C++:第十一讲DFS深搜-CSDN博客

C++:第十讲二分查找-CSDN博客

前缀和与差分:

C++:第九讲前缀和与差分-CSDN博客

贪心:

C++:第八讲贪心算法1-CSDN博客

C++讲解系列(基础入门):

排序:

C++:第七讲冒泡排序-CSDN博客

函数:

C++第6讲max和min函数_c++ min函数-CSDN博客

C++第五讲函数初步-CSDN博客

for循环&数组:

C++第四讲for循环及数组-CSDN博客

if语句&else语句及运算:

C++第三讲:C++中的逻辑运算符及if else语句-CSDN博客

基础:

C++第二讲输入与输出-CSDN博客

C++第一讲认识C++编译器-CSDN博客

欢迎收看,希望大家能三连!

最后认识一下,我是爱编程的喷火龙廖,我们有缘再见!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

03. k210-点灯

本章目的是把开发板上的3个三色LED灯点亮。 1.硬件连接 先看下硬件的LED接线如下: 由上图可知&#xff1a; IO_12&#xff1a;LED_G IO_13&#xff1a;LED_R IO_14&#xff1a;LED_B IO输出低电平"0"&#xff0c;LED点亮&#xff0c;IO输出高电平"1"…

【C++历练之路】二叉搜索树的学习应用及其实现

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 前言&#x1f354;&#xff1a; 我们之前学过一些查找关键数据的办法&#xff0c;排序二分查找。但是这种方法的插入的时间复杂的太高&#xff0c;今天我们来学习一个更好的办法来应对数据查找——二叉搜索树。 目录…

jsp商场会员卡管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 商场会员卡管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.…

高斯消去法 | LU分解 | PA=LU分解(MatLab)

一、问题描述 利用高斯消去法&#xff0c;LU 分解及PALU 分解求解非线性方程组。 二、实验目的 掌握高斯消去法、LU 分解、PALU 分解的算法原理&#xff1b;编写代码实现利用高斯消去法、LU 分解、PALU 分解来求解线性方程组。 三、实验内容及要求 1. 利用顺序高斯消去法求…

C语言标准库所有字符串操作库函数汇总

以下是C语言标准库中字符串操作相关的API列表&#xff0c;这些函数通常在 <string.h> 头文件中定义&#xff1a; 1. strlen - 计算字符串长度&#xff0c;不包括结尾的空字符\0&#xff1a; size_t strlen(const char *str); 2. strcpy - 复制字符串&#xff1a; c…

【Linux】信号-上

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;信号的概念与产生jobs命令普通信号和实…

154基于matlab的二维元胞自动机模拟森林火灾(生命游戏 )和模拟收费站交通流

基于matlab的二维元胞自动机模拟森林火灾&#xff08;生命游戏 &#xff09;和模拟收费站交通流。全国大学生美国建模竞赛&#xff0c;程序已调通&#xff0c;可直接运行。 154 元细胞自动机 森林起火 收费站交通 (xiaohongshu.com)

Python flask 模板详解

文章目录 1 概述1.1 模板简介1.2 templates 文件1.3 简单应用 2 模板语法2.1 for 循环2.2 if 判断 3 模板的继承3.1 格式要求3.2 实现示例3.3 复用父模板的内容&#xff1a;super 1 概述 1.1 模板简介 定义&#xff1a;定义好的 html 文件&#xff0c;用于快速开发 web 页面J…

【linux】git和gdb调试工具

在linux下提交代码同步到gitee 1.创建一个新的仓库&#xff08;演示步骤&#xff09; 2.init 这两个步骤用于识别提交代码的身份&#xff0c;一个你的名字&#xff0c;一个你的邮箱 开启本地仓库 克隆本地仓库成功 我们将这个仓库拷到了111目录底下. 我们发现少了一个.gitig…

Centos 7.5 安装 NVM 详细步骤

NVM&#xff08;Node Version Manager&#xff09;是一个用于管理Node.js版本的工具&#xff0c;它可以让你轻松地在多个版本之间切换。NVM 通过下载和管理 Node.js 的多个版本&#xff0c;为用户提供了一种灵活的方式来使用不同版本的 Node.js。如果你需要更多关于NVM的信息&a…

【云原生之kubernetes系列】--污点与容忍

污点与容忍 污点&#xff08;taints)&#xff1a;用于node节点排斥Pod调度&#xff0c;与亲和效果相反&#xff0c;即taint的node排斥Pod的创建容忍&#xff08;toleration)&#xff1a;用于Pod容忍Node节点的污点信息&#xff0c;即node节点有污点&#xff0c;也将新的pod创建…

超时引发的牛角尖二(hystrix中的超时)

至今我都清楚记得自己负责的系统请求云上关联系统时所报的异常信息。为了解决这个异常&#xff0c;我坚持让这个关联系统的负责人查看&#xff0c;并且毫不顾忌他的嘲讽和鄙视&#xff0c;甚至无视他烦躁的情绪。不过我还是高估了自己的脸皮&#xff0c;最终在其恶狠狠地抛下“…