05高精度(蓝桥杯C/C++基础知识)

本文详细介绍了如何使用高精度算法解决洛谷平台上的四个问题:高精度加法、高精度减法、高精度乘法和两种高精度除法。算法涉及字符串模拟数字、竖式计算和进位处理。
摘要由CSDN通过智能技术生成

目录

高精度加法:洛谷P1601 A+B Problem(高精) 

高精度减法:洛谷P2142 高精度减法 

高精度乘法:洛谷P1303 A*B Problem 

高精度除法(高精度除以低精度):洛谷P1480 A/B Problem 

高精度除法(高精度除以高精度):洛谷P2005 A/B Problem II

概念:

        计算过程中,经常会遇到超出int、long long范围的数字,因此需要引入一个新的算法,叫做高精度算法。
        高精度算法本质是用字符串模拟数字进行计算,再利用数学中竖式计算的思想,逐位进行相关计算。

高精度加法:洛谷P1601 A+B Problem(高精) 

输入格式

分两行输入。a,b≤10500。

输出格式

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

输入样例

1001
9099

输出样例

10100

说明/提示

20% 的测试数据,0≤a,b≤1e9;

40% 的测试数据,0≤a,b≤1e18。

题解

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char s1[505],s2[505];
int a[505],b[505],c[505];
int la,lb,lc;
int main()
{
	scanf("%s",s1);//以字符串形式读入
	scanf("%s",s2);
	la=strlen(s1);
	lb=strlen(s2);
	for(int i=0;i<la;i++)
		a[la-i]=s1[i]-'0';//转成单个数字逆序存入属组
	for(int i=0;i<lb;i++)
		b[lb-i]=s2[i]-'0';
	lc=max(la,lb)+1;//加法存在进位+1
	for(int i=1;i<=lc;i++)
	{
		c[i]+=a[i]+b[i];
		c[i+1]=c[i]/10;//进位
		c[i]%=10;
	}
	if(lc>0&&c[lc]==0) lc--;//除去前导0
	for(int i=lc;i>0;i--)
		printf("%d",c[i]);
	return 0;
}

高精度减法:洛谷P2142 高精度减法 

输入格式

两个整数a,b(第二个可能比第一个大)。

输出格式

结果(是负数要输出负号)。

输入样例

2
1

输出样例

1

说明/提示

 20% 数据a,b 在 long long 范围内;100% 数据0<a,b≤1e10086。

 题解

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
char s1[10090],s2[10090],s3[10090];
int a[10090],b[10090],c[10090];
int la,lb,lc,flag=0;
bool compare(char s1[],char s2[])//如果s1>s2,返回true,否则false
{
	int m=strlen(s1);
	int n=strlen(s2);
	if(m!=n) return m>n;
	for(int i=0;i<m;i++)
	{
		if(s1[i]!=s2[i]) return s1[i]>s2[i];
	}
	return true;
}
int main()
{
	scanf("%s",&s1);
	scanf("%s",&s2);
	if(!compare(s1,s2))//s2>s1时交换两数
	{
		flag=1;
		strcpy(s3,s1);
		strcpy(s1,s2);
		strcpy(s2,s3);
	}
	la=strlen(s1);
	lb=strlen(s2);
	lc=max(la,lb);
	for(int i=0;i<la;i++)
		a[la-i]=s1[i]-'0';
	for(int i=0;i<lb;i++)
		b[lb-i]=s2[i]-'0';
	for(int i=1;i<=lc;i++)
	{
		if(a[i]<b[i])//当被减数较小时
		{
			a[i+1]--;//被减数借位
			a[i]+=10;
		}
		c[i]=a[i]-b[i];
	}
	while(c[lc]==0&&lc>1) lc--;
	if(flag==1) cout<<"-";
	for(int i=lc;i>0;i--)
		printf("%d",c[i]);
	return 0;
}

高精度乘法:洛谷P1303 A*B Problem 

输入格式

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

输出格式

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

输入样例

1 
2

输出样例

2

说明/提示

每个非负整数不超过1e2000。

 题解

#include<iostream>
#include<cstring>
using namespace std;
char a1[10001],b1[10001];
int a[10001],b[10001],c[10001];
int la,lb,lc;
int main ()
{
    cin>>a1>>b1;
    la=strlen(a1);
	lb=strlen(b1);
	lc=la+lb;
    for(int i=1;i<=la;i++)a[i]=a1[la-i]-'0';
    for(int i=1;i<=lb;i++)b[i]=b1[lb-i]-'0';
	for(int i=1;i<=lb;i++)
	for(int j=1;j<=la;j++)
	c[i+j-1]+=a[j]*b[i];
    for(int i=1;i<lc;i++)
	if(c[i]>9)
	{
		c[i+1]+=c[i]/10;
		c[i]%=10;
	}
    while(c[lc]==0&&lc>1)lc--;
    for(int i=lc;i>=1;i--)cout<<c[i];
    return 0;
}

高精度除法(高精度除以低精度):洛谷P1480 A/B Problem 

方法:逐位试商法

输入格式

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

输出格式

一行,商的整数部分。

输入样例

10
2

 输出样例

5

说明/提示 

0≤a≤1e5000,1≤b≤1e9。 

题解

#include<iostream>
#include<cstring>
using namespace std;
char a[5050];
long long b,la,lc,x,s1[5050],c[5050];
int main()
{
	cin>>a>>b;//输入被除数和除数 
	la=strlen(a);
	lc=1;
	for(int i=1;i<=la;i++)
	s1[i]=a[i-1]-'0';//将被除数逐位存入数组s1 
	for(int i=1;i<=la;i++)
	{
		c[i]=(x*10+s1[i])/b;
		x=(x*10+s1[i])%b;
	}
	while(c[lc]==0&&lc<la) lc++;//删除前导0 
	for(int i=lc;i<=la;i++) cout<<c[i];
	return 0;
} 

高精度除法(高精度除以高精度):洛谷P2005 A/B Problem II 

方法:减法模拟除法

题目描述

给出正整数 N 和 M,请你计算 N÷M(N/M 的下取整)。

输入格式

两行,两个正整数,N 和 M。

输出格式

一行,一个整数,表示N÷M。

输入样例

1000 
333

输出样例 

3

说明/提示

对于60% 的数据:N,M≤750!,答案≤7!。

对于100% 的数据:N,M≤6250!,答案≤13!。

题解

#include<iostream>
#include<cstring>
using namespace std;
char s1[100010],s2[100010];
int a[100010],b[100010],c[100010],tmp[100010];//a为被除数,b为除数,c为商 
void init(int *x)
{
	char s[100010];
	cin>>s;
	x[0]=strlen(s);
	for(int i=0;i<x[0];i++)
	{
		x[x[0]-i]=s[i]-'0';//为了便于计算,将字符串转为数字,并倒序存储 
	}
}
void print(int a[])
{
	if(a[0]==0) {cout<<0;return;}
	for(int i=a[0];i>0;i--) cout<<a[i];
	return;
}
int compare(int a[],int b[])//a>b返回1,a=b返回0,a<b返回-1 
{
	if(a[0]>b[0]) return 1;//a的位数大于b,则a>b 
	if(a[0]<b[0]) return -1;
	for(int i=a[0];i>0;i--)
	{
		if(a[i]>b[i]) return 1;
		if(a[i]<b[i]) return -1;
	}
	return 0;
}
void minu(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]=a[i]-b[i];
	}
	while(a[a[0]]==0 && a[0]>0) a[0]--;
} 
void numcpy(int p[],int q[],int n)//将p数组整体移动n位到q数组中 
{
	for(int i=1;i<=p[0];i++) q[i+n-1]=p[i];
	q[0]=p[0]+n-1;
}
int main()
{
	init(a);
	init(b);
	c[0]=a[0]-b[0]+1;
	for(int i=c[0];i>=1;i--)
	{
		memset(tmp,0,sizeof(tmp));
		numcpy(b,tmp,i);
		while(compare(a,tmp)>=0)
		{
			c[i]++;
			minu(a,tmp); 
		}
	} 
	while(c[c[0]]==0&&c[0]>0) c[0]--;
	print(c);
	//cout<<endl; 
	//print(a);//余数 
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值