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

news2024/9/22 5:04:47

每日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.coloradmin.cn/o/1436861.html

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

相关文章

详细关于如何解决mfc140.dll丢失的步骤,有效修复mfc140.dll文件丢失的问题。

mfc140.dll文件是Microsoft Visual Studio 2015程序集之一&#xff0c;它包含用于支持多种功能的代码和库。当这个mfc140.dll文件丢失时&#xff0c;可能会导致相关程序运行出错甚至无法运行。很多用户可能会遇到mfc140.dll丢失的问题&#xff0c;但是这并不是不可解决的困难。…

【自然语言处理-工具篇】spaCy<1>--介绍及安装指南

目录 前言 安装指南 pip conda spaCy升级 总结 前言 spaCy是一个开源的自然语言处理库,用于处理和分析文本数据。它提供了许多功能,包括分词、词性标注

cs50x 2024 -Lecture 0

cs50x 2024 -Lecture 0 01:43 哈佛大学CS50课程介绍 01:43CS50是哈佛大学的计算机科学和编程入门课程。 05:17计算机科学是一种通用的问题解决方式&#xff0c;适用于各个领域。 06:32课程将教授C、Python、SQL和JavaScript等编程语言。 08:18 计算机科学的重要性和二进制表…

【CSS】css如何实现字体大小小于12px?

【CSS】css如何实现字体大小小于12px? 问题解决方案transform: scale(0.5)&#xff08;常用&#xff09;SVG 矢量图设置text 问题 文字需要显示为12px&#xff0c;但是小于12px的&#xff0c;浏览器是显示不来的 解决方案 transform: scale(0.5)&#xff08;常用&#xff0…

Bert下载和使用(以bert-base-uncased为例)

Bert官方github地址&#xff1a;https://github.com/google-research/bert?tabreadme-ov-file 【hugging face无法加载预训练模型】OSError&#xff1a;Can‘t load config for ‘./bert-base-uncased‘. If you‘re trying 如何下载和在本地使用Bert预训练模型 以bert-base-u…

should be also和should also be

will also be 是正确的 但老师和新概念的两个说法都没有错. will also be 是固定搭配.就好像will not be一样, 限定词加在be前.老师说的是陈述之类的句型 Nbe动词alson/adj/动词短语.例&#xff1a;He is also good at physic. should be also还是should also be also应该插在…

期权定价模型系列【14】期权复制—Delta动态复制误差计算

动态复制 直接使用期权进行对冲存在的问题之一是成本较高。假设我们多头一个看涨期权进行对冲,除本 身的交易费用之外,更多的隐性成本来自于期权的时间价值——期权价值等于内在价值与时间价值之 和,但在时间逐渐临近到期日的过程中,时间价值不断损耗,直至到期日为 0,如…

C++泛编程(4)

类模板高级&#xff08;1&#xff09; 1.类模板具体化部分具体化完全具体化 2.类模板与继承2.1模板类继承普通类2.2普通类继承模板类的实例化版本2.3普通类继承类模板2.4模板类继承模板类2.5模板类继承模板参数给出的类 1.类模板具体化 有了函数模板具体化的基础&#xff0c;学…

STL算法(中)

常用排序算法 sort 功能描述&#xff1a; 对容器内元素进行排序 函数原型&#xff1a; sort(iterator beg, iterator end, _Pred) ; // 按值查找元素&#xff0c;找到返回指定位置迭代器&#xff0c;找不到返回结束迭代器位置 // beg 开始迭代器 // end 结束迭代器 …

1-3 mininet中使用python API直接拓扑定义以及启动方式对比

作为SDN网络中搭建拓扑非常重要的仿真平台&#xff0c;我们可以使用mininet默认的库内拓扑文件&#xff0c;也可以使用python语言进行自定义拓扑。使用python进行拓扑定义时&#xff0c;不同的定义方式将导致其启动的方式由所不同。 一、采用最原始的命令启动方式&#xff1a; …

Redis——事件

Redis服务器是一个事件驱动程序&#xff0c;服务器需要处理以下两种事件&#xff1a; 文件事件(file event)&#xff1a;Redis服务器通过套接字与客户端(或者其他Redis服务器)进行连接&#xff0c;而文件事件就是服务器对套接字操作的抽象(linux下一切皆文件&#xff0c;返回的…

TP框架 之think-auth权限认证

一、安装think-auth composer require 5ini99/think-auth二、数据表 -- ---------------------------- -- think_auth_rule&#xff0c;规则表&#xff0c; -- id:主键&#xff0c;name&#xff1a;规则唯一标识, title&#xff1a;规则中文名称 status 状态&#xff1a;为1正常…

【日志记录】——单片机可执行文件合并

一&#xff1a;需求场景 现在有一片单片机&#xff0c;执行程序包括自定义boot和应用程序app, 在将打包好的固件给到生产时有以下问题&#xff0c;由于要通过jlink烧录boot&#xff0c;然后上电启动boot&#xff0c;通过boot烧录初始化程序&#xff0c;过程过于复杂&#xff0…

基于ESP-WROOM-32的双串口通信并显示到OLED显示屏上

目录 开发板引脚图 Arduino环境配置1.ESP32开发版下载2.Arduino开发板选择 -> ESP32 Dev Module3.安装驱动库 接线图Arduino代码现象演示 开发板 ESP-WROOM-32 引脚图 Arduino环境配置 1.ESP32开发版下载 选择 esp32 by Espressif Systems 2.Arduino开发板选择 -> E…

一文读懂「四大主流计算芯片 CPU、GPU、ASIC、FPGA」特点和场景

纵观人类历史&#xff0c;从结绳计数、木制计数到巴比伦的粘土板上的刻痕&#xff0c;再到中国古代的算盘&#xff0c;社会生产力的提高与当时所采用的计算工具密切相关。计算工具能力越强&#xff0c;就能大幅缩短人类解决复杂问题的时间&#xff0c;社会生产力水平自然就会越…

微信小程序解决华为手机保存图片到相册失败

1.新增隐私设置 2.优化代码 新增uni.authorize判断 _saveCode() {let that this;console.log(点击了保存图片)console.log(this.result)uni.authorize({scope: scope.writePhotosAlbum,success(e) {console.log(e)if (this.result ! "") {uni.saveImageToPhotosAlb…

RCS系统之:界面设计

RCS Floor Manager设计的主要目的&#xff1a; 实时监控机器人状态实时查看货架状态查看机器人任务状态查看捡货站的任务状态地图的状态信息其他元素&#xff0c;如打包机&#xff0c;机械臂的状态动态的编辑地图元素信息等等 有兴趣的可以留言一起交流下

[office] Excel2007在工作簿中创建区域名称 #职场发展#经验分享

Excel2007在工作簿中创建区域名称 Excel 提供了几种不同的方法来创建区域名称。但在开始之前&#xff0c;必须注意关于可接受内容的重要规则: 名称不能含有空格。可以用一个下划线字符来代替空格(如Annual Total ) 。 可以使用字母和数字的任意组合&#xff0c;但是名称必须以…

Redis + Lua 实现分布式限流器

文章目录 Redis Lua 限流实现1. 导入依赖2. 配置application.properties3. 配置RedisTemplate实例4. 定义限流类型枚举类5. 自定义注解6. 切面代码实现7. 控制层实现8. 测试 相比 Redis事务&#xff0c; Lua脚本的优点&#xff1a; 减少网络开销&#xff1a;使用Lua脚本&…

C++ STL精通之旅:向量、集合与映射等容器详解

目录 常用容器 顺序容器 向量vector 构造 尾接 & 尾删 中括号运算符 获取长度 清空 判空 改变长度 提前分配好空间 代码演示 运行结果 关联容器 集合set 构造 遍历 其他 代码演示 运行结果​编辑 映射map 常用方法 构造 遍历 其他 代码演示1​编…