目录
高精度除法(高精度除以低精度):洛谷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;
}