高精度算法讲解以及相关练习题

概念

在我们进行计算的过程中,经常会遇到几十位,甚至几百位的数字的计算问题,也有可能会遇到小数点后几十位,几百位的情况,而我们面对这样的情况下,long long和double的数据范围显然是不够使用的了。因此这时,我们就需要引入一个新的算法,叫做高精度算法
高精度算法本质上是用字符串进行模拟,再利用类似于数学里的竖式的形式,一位一位进行计算

处理

高精度计算中需要处理好以下几个问题:

1.数据的接收方法和存储方法

数据的接收和存储:采用string或char方式输入,利用字符转数字的操作运算,将每一位取出,存入int类型的数组中 .

下面是输入数据的伪代码:

int main(){int a[10005];memset(a,0,sizeof(a));string s;cin >> s; len = s.size();//也可以写成s.length -->其作用是计算字符串位数for(int i=1;i<=len;i++)     a[i]=s[len-i]-'0';//将字符串s转换为数组a,倒序存储
}


2.进位、借位的处理.

加法进位: c[i] = a[i] + b[i]
 

if(c[i]>=10){c[i]%=10;++c[i++];
}


 
减法借位: c[i] = a[i] - b[i]

if(a[i]<b[i]){--a[i+1];a[i]+=10;   
} 


乘法进位: c[i + j - 1] = a[i] * b[j] + x + c[i + j - 1];
 

x=c[i+j-1]/10;
c[i+j-1]%=10;
高精度加法和减法

在以前数据较小的时候,输入两个数到变量中,然后用运算符求它们的和后输出 .但是我们知道,在 C++ 语言中任何数据类型都有一定的范围. 当两个加数很大时,以前的方法显然不能求出答案(放不下那么大的数据),因此我们需要寻求另一种方法 .在读小学时,我们做加法都采用竖式方法 . 这样我们方便写出两个整数相加的算法.减法也是同样

        所以在程序中,我们也可以用模拟的方法求解。我们只要模拟出来竖式的过程即可

以下是高精度加减法的程序:

//加法
#include<bits/stdc++.h>
using namespace std;
string a,b,d;
int j;
int main(){cin>>a>>b;while(a.size()<b.size())a='0'+a;while(a.size()>b.size())b='0'+b;for(int i=a.size()-1;i>=0;i--){if(int(a[i]-'0')+int(b[i]-'0')+j>=10)d=char(int(a[i]-'0')+int(b[i]-'0')+j-10+'0')+d,j=1;else d=char(int(a[i]-'0')+int(b[i]-'0')+'0')+d,j=0;}if(j==1)d='1'+d;cout<<d;return 0;
} 
//减法
#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int a[240],b[240],c[240];
char q='+';
int main()
{int p;cin>>s1>>s2;if(s1.size()<s2.size()||(s1.size()==s2.size()&&s1<s2)){q='-';swap(s1,s2);}for(int i=0;i<s1.size();i++)a[i]=s1[s1.size()-i-1]-'0';for(int i=0;i<s2.size();i++)b[i]=s2[s2.size()-i-1]-'0';if(q=='-')cout<<'-';for(int i=0;i<s1.size();i++){if(a[i]<b[i])a[i+1]-=1,a[i]+=10;c[i]=a[i]-b[i];}int len=s1.size();for(int i=len-1;i>=0;i--)if(c[i]!=0){p=i;break;}for(int i=p;i>=0;i--)cout<<c[i];return 0;
}
高精度乘法

类似加法,使用竖式。在做乘法时,同样也有进位

乘法下标规律:

c[i+j−1]=a[i]+b[j]+x+c[i+j−1]

#include<bits/stdc++.h>
using namespace std;
char a1[10000],a2[100000];
int a[10000],b[10000],c[10000];
int len_a,len_b,len_c=1;
int main(){cin>>a1>>a2;len_a=strlen(a1);len_b=strlen(a2);for(int i=1;i<=len_a;i++)a[i]=a1[len_a-i]-'0';for(int i=1;i<=len_b;i++)b[i]=a2[len_b-i]-'0';for (int i=1;i<=len_a;i++)for(int j=1;j<=len_b;j++)c[i+j-1]+=a[i]*b[j];for(int i=1;i<len_a+len_b;i++)if(c[i]>9)c[i+1]+=c[i]/10,c[i]%=10;int len=len_a+len_b;while(c[len]==0&&len>1)len--;for(int i=len;i>=1;i--)cout<<c[i];return 0;
}
高精度除法

除法高精度分两种情况:

①高精除以低精

②高精除以高精

但是我们想想,我们可不可以把低精看成高精去计算呢?

所以不管是低精还是高精,我们都可以看成都是高精度去模拟计算

高精除以高精使用减法模拟除法,对被除数的每一位都减去除数,一直减到当前位置的数字

代码如下:

#include<bits/stdc++.h>
using namespace std;
int dividend[5000] = {0};
int quotient[5000] = {0};
int main() {string a;int divisor;cin >> a >> divisor;int al = a.length();for (int i = 0; i < al; i++){dividend[i] = a[i]-'0';}long long remainder = 0;for (int i = 0;i < al;i++){   quotient[i] = (remainder * 10 + dividend[i]) / divisor;remainder = remainder * 10 + dividend[i] - (quotient[i] * divisor);}int zeroflag = 0;for (int i = 0; i < al ; i++){if (quotient[i] == 0 && zeroflag == 0 && i < al-1){continue;}zeroflag = 1;cout << quotient[i];}return 0;
}

习题

计算N的阶乘

请计算n的阶乘(1<=n<=100)

n的阶乘计算公式为:n!=n*(n-1)*(n-2)*...*1,如:5!=5*4*3*2*1=120

输入

一个整数n(1<=n<=100)

输出

n的阶乘

样例输入
20
样例输出
2432902008176640000
代码:
#include<bits/stdc++.h>
using namespace std;
int n,l=1,a[100000]={0,1};
int main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=l;j++)a[j]*=i;for(int j=1;j<=l;j++)if(a[j]>=10)a[j+1]+=a[j]/10,a[j]%=10;while(a[l+1])l++,a[l+1]=a[l]/10,a[l]%=10;}for(int i=l;i>=1;i--)cout<<a[i];return 0;
}
破译密码

我军拦截敌军传递了2个数字串,后经侦查得知,这两个数字串中包含了一个很重要的密码,这个密码的破译方式为,用这两个数字串中的大数 – 小数,得到结果后将结果转换为16进制(转换时如需使用字母请使用大写字母),就是敌军想要传递的密码。

比如,敌军传递了下列两个数字串:

99999999999999999999999999999999999999973

99999999999999999999999999999999999999999

大数 – 小数的差值 = 26,转换为16进制的结果为1A,也就是1A就是敌军想要传递的密码。

请编程实现破译密码的过程。

输入 

输入有2行,分别是2个不超过200位的整数,且已知2个整数的差是一个不超过18位的整数。

输出

输出按题意计算出的16进制数。

样例输入
99999999999999999999999999999999999999973
99999999999999999999999999999999999999999

 样例输出

1A
代码:
#include<bits/stdc++.h>
using namespace std;
string s1,s2,s;
long long a[240],b[240],c[240],sum,p;
int main()
{cin>>s1>>s2;if(s1.size()<s2.size()||(s1.size()==s2.size()&&s1<s2))swap(s1,s2);for(long long i=0;i<s1.size();i++)a[i]=s1[s1.size()-i-1]-'0';for(long long i=0;i<s2.size();i++)b[i]=s2[s2.size()-i-1]-'0';for(long long i=0;i<s1.size();i++){if(a[i]<b[i])a[i+1]-=1,a[i]+=10;c[i]=a[i]-b[i];}long long len=s1.size();for(long long i=len-1;i>=0;i--){if(c[i]!=0){p=i;break;}}for(long long i=p;i>=0;i--)sum=sum*10+c[i];if(sum==0){cout<<0;return 0;}while(sum){if(sum%16<=9)s=char(sum%16+'0')+s;else s=char(sum%16-10+'A')+s;sum/=16;}cout<<s;return 0;
}
洛谷P2687

“逢低吸纳”是炒股的一条成功秘诀。如果你想成为一个成功的投资者,就要遵守这条秘诀:

"逢低吸纳,越低越买"

这句话的意思是:每次你购买股票时的股价一定要比你上次购买时的股价低.按照这个规则购买股票的次数越多越好,看看你最多能按这个规则买几次。

给定连续的N天中每天的股价。你可以在任何一天购买一次股票,但是购买时的股价一定要比你上次购买时的股价低。写一个程序,求出最多能买几次股票。

以下面这个表为例, 某几天的股价是:

天数 1 2 3 4 5 6 7 8 9 10 11 12

股价 68 69 54 64 68 64 70 67 78 62 98 87

这个例子中, 聪明的投资者(按上面的定义),如果每次买股票时的股价都比上一次买时低,那么他最多能买4次股票。一种买法如下(可能有其他的买法):

天数 2 5 6 10

股价 69 68 64 62

输入格式

第1行: N (1 <= N <= 5000), 表示能买股票的天数。

第2行以下: N个正整数 (可能分多行) ,第i个正整数表示第i天的股价. 这些正整数大小不会超过longint(pascal)/long(c++).

输出格式

只有一行,输出两个整数:

能够买进股票的天数和长度达到这个值的股票购买方案数量

在计算方案的数量的时候,如果两个方案的股价序列相同,那么这样的两个方案被认为是相同的(只能算做一个方案)。因此,两个不同的天数序列可能产生同一个股价序列,这样只能计算一次。

样例输入

12
68 69 54 64 68 64 70 67
78 62 98 87

样例输出

4 2
代码:
#include<bits/stdc++.h>
using namespace std;
int dp[5001];
int a[5001];
int a1[110],b1[110],c1[110];
//int num[5001];
struct node{int len,zu[110];node operator + (const node x)const{memset(a1,0,sizeof(a1));memset(b1,0,sizeof(b1));memset(c1,0,sizeof(c1));node res;res.len=0;for(int i=1,j=len;i<=len;i++,j--)a1[i]=zu[j];for(int i=1,j=x.len;i<=x.len;i++,j--)b1[i]=x.zu[j];for(int i=1;i<=max(len,x.len);i++){c1[i]+=a1[i]+b1[i];c1[i+1]+=c1[i]/10;c1[i]=c1[i]%10;}int l=max(len,x.len);while(c1[l+1]){l++;c1[l+1]=c1[l]/10;c1[l]=c1[l]%10;}res.len=l;for(int i=1,j=l;i<=l;i++,j--)res.zu[i]=c1[j];return res;}
}num[5001];
int main()
{int n;cin>>n;for(int i=0;i<n;i++){cin>>a[i];}for(int i=0;i<=n;i++){num[i].len=1;num[i].zu[1]=1;int tmp=1<<30;for(int j = i-1; j>=0;j--)if(a[j]>a[i]){if(dp[j]>= dp[i]){tmp = a[j];dp[i]= dp[j]+1;num[i]= num[j];}else if (dp[j]+1 == dp[i]&& a[j]< tmp){tmp = a[j];num[i]=num[i]+num[j];}}}printf("%d ",dp[n]);for(int i=1;i<=num[n].len;i++)printf("%d",num[n].zu[i]);
}
国王游戏

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

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

输入格式

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

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

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

输出格式

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

样例输入

3 
1 1 
2 3 
7 4 
4 6 

样例输出

2
说明/提示

【输入输出样例说明】

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

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

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

按22、33、11这样排列队伍,获得奖赏最多的大臣所获得金币数为 99;

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

按33、22、11 这样排列队伍,获得奖赏最多的大臣所获得金币数为 99。

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

【数据范围】

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

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

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

对于 60%60% 的数据,保证答案不超过 109;

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

代码:
#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));xx=hmul(xx,tur_str(a[i].l));}cout<<ans<<endl;return 0;
}

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

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

相关文章

MATLAB初学者入门(4)—— 高级特性和实用技巧

继续深入MATLAB优化模型求解&#xff0c;我们可以探索更多的高级特性和实用技巧&#xff0c;这有助于提高求解效率和结果的精确度。以下内容将涉及到一些高级配置选项、多目标优化和稳健性优化。 高级配置选项 在使用fmincon或其他MATLAB优化求解器时&#xff0c;你可以配置多…

playwright-断言

前言 playwright 提供了一个 expect方法 用于断言 断言 断言描述expect(locator).to_be_checked()Checkbox已勾选expect(locator).to_be_disabled()元素被禁用expect(locator).to_be_editable()元素可编辑expect(locator).to_be_empty()内容为空expect(locator).to_be_enable…

探索嵌入式系统:快速入门指南概览

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

OpenHarmony实战开发-性能测试工具SmartPerf Editor使用指导

概述 SmartPerf Editor是一款PC端桌面应用&#xff0c;通过监测、采集应用运行时FPS、CPU、GPU、Memory、Battery、Network等性能数据&#xff0c;帮助开发者了解应用的性能状况。SmartPerf Editor还集成了DrawingDoc功能&#xff0c;可录制Render Service绘制指令&#xff0c…

Android Perfetto 监控应用启动耗时

Perfetto 是一个 Google 开发的用于安卓系统性能监控和调试的工具&#xff0c;它旨在提供实时数据收集和可视化功能&#xff0c;帮助我们分析和优化应用程序的性能表现。Perfetto 可以捕获系统事件、CPU、内存、网络、GPU 等性能指标数据&#xff0c;并将其记录为轻量级的 Trac…

开发环境中的调试视图(IDEA)

当程序员写完一个代码时必然要运行这个代码&#xff0c;但是一个没有异常的代码却未必满足我们的要求&#xff0c;因此就要求程序员对已经写好的代码进行调试操作。在之前&#xff0c;如果我们要看某一个程序是否满足我们的需求&#xff0c;一般情况下会对程序运行的结果进行打…

茶饮门店本地生活抖音团购运营方案计划书

【干货资料持续更新&#xff0c;以防走丢】 茶饮门店本地生活抖音团购运营方案计划书 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PPT可编辑80页&#xff08;完整资料包含以下内容&#xff09; 目录 抖音本地生活运营方案 1. 账号基础搭建与优化 - 门店账号…

练习题(2024/4/23)

1分发糖果 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果&#xff0c;计算并返回…

Php-WebView 现代跨平台 GUI分享

GitHub :php-webview 一个用于 C/C 的小型跨平台 Web 视图库&#xff0c;用于构建现代跨平台 GUI。 该项目的目标是为最广泛使用的平台创建一个通用的 HTML5 UI 抽象层。 它支持双向 JavaScript 绑定&#xff08;从 C/C 调用 JavaScript 和从 JavaScript 调用 C/C&#xff09;。…

ClickHouse 高可用之副本

文章目录 ClickHouse 副本支持副本的引擎配置高可用副本副本应用1.副本表概述2.创建副本表3.写入模拟数据4.副本验证 扩展 —— 在 Zookeeper 中查看副本表信息 ClickHouse 副本 ClickHouse 通过副本机制&#xff0c;可以将数据拷贝存储在不同的节点上。这样&#xff0c;如果一…

Linux登录后的提示信息在哪里配置及配置方法

一、在哪配置 首先&#xff0c;用户的个性化提示信息可以通过编辑用户的.bashrc或.bash_profile文件来实现。这些文件通常位于用户的主目录下。你可以使用文本编辑器&#xff08;如vi、nano或gedit&#xff09;打开这些文件&#xff0c;并在文件的末尾添加你想要的个性化提示信…

我的世界服务器设计思路应该是什么样?

我的世界服务器设计思路可以从这4个方面展开&#xff1a;1.选择你喜欢的东西&#xff1b;2.认识你的极限&#xff1b;3.注入新鲜元素&#xff1b;4.让服务器变得享受且有回报。 1.选择你喜欢的东西 设计服务器的首要规则是创造一些你自己会积极享受玩的东西。没有人愿意花费宝…

在Spring boot中指定随机可用的端口

​ 正常情况下每个spring boot启动都有固定的端口&#xff0c;也就是8080&#xff0c;如果启动多个项目&#xff0c;很容易出现端口冲突&#xff0c;那么怎么解决这个问题呢&#xff1f; 解决方案1&#xff1a; random 随机端口 ​ 在spring boot中&#xff0c;可以通过${ran…

linux的一些实用操作

快捷键 强制停止 ctrlc强制停止或退出命令的输入 退出登出 ctrld强制退出用户登录或退出某些程序的专属页面&#xff08;如py&#xff09; ps&#xff1a;不能退出vi/vim 历史命令搜索 history可以查看历史命令&#xff0c;用来复制粘贴 在使用history之后&#xff0c;…

fnm:Rust开发的高效Node版本管理工具

简介 fnm 是一个基于 Rust 开发的 Node 版本管理工具&#xff0c;它的目标是提供一个快速、简单且可靠的方式来管理 Node.js 的不同版本。同时&#xff0c;它是跨平台的&#xff0c;支持 macOS、Linux、Windows。&#x1f680; Fast and simple Node.js version manager, buil…

pycharm-git 配置(1)

1.安装git2.pycharm 中配置git 插件 弹出Git版本号&#xff0c;即配置成功。3.创建本地仓库 VCS->VCS operations->create repository->设置本地目录 左下角可以看到git本地仓库git可以看到push,commit。 4.配置远方仓库&#xff0c;此时确保git上是有这个项目…

【linux】chmod权限开放(整个文件夹)

文章目录 起因权限查看权限修改 失败权限修改成功 起因 想要共享conda环境给同事&#xff0c;发现同事没权限。 权限查看 ls #查看当前目录 ls -l # 查看当前目录的东西和权限正常情况下是显示 三个rwx分别属于user&#xff0c;group&#xff0c;others 前面第一个rwx 是针…

美容预约小程序:简单三步,开启高效预约模式

在当今的数字化时代&#xff0c;一个小程序可以极大地提高美容院的效率和客户满意度。下面我们将详细说明如何通过以下步骤来搭建一个美容院预约小程序。 首先&#xff0c;你需要注册并登录到乔拓云网&#xff0c;这是 一个在线平台&#xff0c;可以帮助你快速创建并管理你的小…

腾讯云服务器,部署mysql数据库后无法远程访问?

一&#xff0c;首先确定自己部署的数据库&#xff0c;是否可以正常登录&#xff0c;验证部署是否是否成功 mysql -u root -p二、放开mysql远程访问权限&#xff0c;依次输入这些命令 create user root% identified with mysql_native_password by xxxxx; grant all privilege…

k8s学习(三十六)centos下离线部署kubernetes1.30(单主节点)

文章目录 服务器准备工作一、升级操作系统内核1 查看操作系统和内核版本2 下载内核离线升级包3 升级内核4 确认内核版本 二、修改主机名/hosts文件1 修改主机名2 修改hosts文件 三、关闭防火墙四、关闭SELINUX配置五、时间同步1 下载NTP2 卸载3 安装4 配置4.1 主节点配置4.2 从…