今天补的是之前所看到的高精度算法。
主要从洛谷和杭电几条经典题目入手。
原理:因为long long乃至double能表示的范围有时候达不到题目所需要的范围。所以利用数组模拟大数的加减乘除。
首先感谢大佬详细的教学@Angel_Kitty
我这篇就相当于学习大佬教学的心得吧
高精度加法
P1061
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
int a[10050],b[10050],c[10050];
int lena,lenb,lenc;
char s1[10050],s2[10050];
int main()
{
scanf("%s %s",s1+1,s2+1);
lena=strlen(s1+1);
lenb=strlen(s2+1);
for(int i=1;i<=lena;i++) a[i]=s1[lena-i+1]-'0';
for(int i=1;i<=lenb;i++) b[i]=s2[lenb-i+1]-'0';
lenc=max(lena,lenb);
for(int i=1;i<=lenc;i++){
c[i]=c[i]+a[i]+b[i];
c[i+1]=c[i]/10;
c[i]=c[i]%10;
}
while(c[lenc+1]>0) lenc++;
for(int i=lenc;i>0;i--) printf("%d",c[i]);
}
注意点:
1.在这段代码里面是把数倒着存储的,方便处理有进位的情况
2.然后就是普通的模拟
高精度乘法
P1303
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
using namespace std;
int a[10050],b[10050],c[10050];
int lena,lenb,lenc;
char s1[10050],s2[10050];
int main()
{
scanf("%s %s",s1+1,s2+1);
lena=strlen(s1+1);
lenb=strlen(s2+1);
for(int i=1;i<=lena;i++) a[i]=s1[lena-i+1]-'0';
for(int i=1;i<=lenb;i++) b[i]=s2[lenb-i+1]-'0';
lenc=lena+lenb-1;
for(int i=1;i<=lena;i++){
for(int j=1;j<=lenb;j++){
c[i+j-1]+=a[i]*b[j];
c[i+j]+=c[i+j-1]/10;
c[i+j-1]%=10;
}
}
while(c[lenc+1]>0) lenc++;
while (c[lenc]==0&&lenc>1)lenc--;//判断位数
for(int i=lenc;i>0;i--) printf("%d",c[i]);
}
注意的是:这和大佬的代码稍微有所不同在于判断位数,防止出现“000”之类的情况。
HDU1042
利用的是高精度乘以单精度
#include<iostream>
using namespace std;
void hanshu(int n)
{
int digit=1;
int carry;//进位
int j,temp;
int a[500050]={1};
for(int i=1;i<=n;i++)
{
for(carry = 0, j = 1; j <= digit; ++j) {
temp = a[j - 1] * i + carry;
a[j - 1] = temp % 10;
carry = temp / 10;
}
while(carry) {
a[++digit - 1] = carry % 10;
carry /= 10;
}
}
for(int k=digit-1;k>=0;k--)cout<<a[k];
}
int main()
{
int n;
while(cin>>n)
{
hanshu(n);
cout<<endl;
}
}