高精度板子
前言:写一写自己高精度易错的地方,内容并不适合初学者,还有高精除高精的锅蒟蒻补不上了.
I.高精加法
记住进位数x的定义,并记得最后x!=0时将x加上.
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define e exit(0) #define R register char s[510],t[510]; int x,id,lena,lenb,a[510],b[510],c[510]; int main() { // freopen("s.in","r",stdin); // freopen("s.out","w",stdout); scanf("%s",s),scanf("%s",t); lena=strlen(s),lenb=strlen(t); for(R int i=0;i<lena;++i) a[i]=s[lena-i-1]-'0'; for(R int j=0;j<lenb;++j) b[j]=t[lenb-j-1]-'0'; while(id<lena||id<lenb) { c[id]=a[id]+b[id]+x; x=c[id]/10; c[id]%=10; ++id; } --id; if(x!=0) c[++id]=x; for(R int j=id;j>=0;--j) printf("%d",c[j]); return 0; }
II.高精减法
①理解借位x的定义,每次做减法时要考虑是否要借位,并在这之后将x变为1或0.
②注意被减数比减数大的情况,要在运算之前将次交换.
③清前导零时,要特判"0-0"的特殊情况.
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define e exit(0) #define R register char a[10010],b[10010]; int x,id,lena,lenb,lens,lent,s[10010],t[10010],c[10010]; bool check() { if(lena<lenb) return true; else if(lena>lenb) return false; else if(lena==lenb) { for(R int i=0;i<lena;++i) if(a[i]<b[i]) return true; return false; } } void chang() { printf("-"); char c[10010]; for(R int i=0;i<lena;++i) c[i]=a[i]; for(R int i=0;i<lenb;++i) a[i]=b[i]; for(R int i=0;i<lena;++i) b[i]=c[i]; swap(lena,lenb); } int main() { // freopen("s.in","r",stdin); // freopen("s.out","w",stdout); scanf("%s",a),scanf("%s",b); lena=strlen(a),lenb=strlen(b); if(check()) chang(); lens=lena,lent=lenb; for(R int i=0;i<lens;++i) s[i]=a[lena-i-1]-'0'; for(R int i=0;i<lent;++i) t[i]=b[lenb-i-1]-'0'; while(id<lena||id<lenb){ if(s[id]-t[id]-x<0){ c[id]=s[id]+10-t[id]-x; x=1; } else if(s[id]-t[id]-x>=0){ c[id]=s[id]-t[id]-x; x=0; } ++id; } --id; while(c[id]==0&&id>=0) --id; if(id==-1) { cout<<0; return 0; } for(R int i=id;i>=0;--i) cout<<c[i]; return 0; }
III.高精乘
①建议字符串的id从1开始.
②特判" 0*0 "的情况.
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define R register char s[2010],t[2010]; int a[2010],b[2010],c[5010],lena,lenb,lenc,x; int main() { // freopen("s.in","r",stdin); // freopen("s.out","w",stdout); scanf("%s",s+1),scanf("%s",t+1); lena=strlen(s+1),lenb=strlen(t+1); if((lena==1&&s[1]=='0')||(lenb==1&&t[1]=='0')) { printf("0"); return 0; } for(R int i=1;i<=lena;++i) a[i]=s[lena-i+1]-'0'; for(R int i=1;i<=lenb;++i) b[i]=t[lenb-i+1]-'0'; for(R int i=1;i<=lena;++i) { x=0; for(R int j=1;j<=lenb;++j) { c[i+j-1]=a[i]*b[j]+c[i+j-1]+x; x=c[i+j-1]/10; c[i+j-1]%=10; } c[lenb+i]=x; } lenc=lena+lenb; while(c[lenc]==0) --lenc; for(R int i=lenc;i>=1;--i) printf("%d",c[i]); return 0; }
IV.高精除低精
够除就除,不够除就存,注意前导0.
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define R register #define ll long long char s[5010]; long long a[5010],c[5010],lena,last,deep,b,sur; int main() { // freopen("s.in","r",stdin); // freopen("s.out","w",stdout); scanf("%s",s+1),scanf("%lld",&b); lena=strlen(s+1); for(R ll i=1;i<=lena;++i) a[i]=s[i]-'0'; for(R ll i=1;i<=lena;++i){ last=last*10+a[i]; if(last<b&&sur==1){c[++deep]=0;} else if(last>=b){ c[++deep]=last/b; last%=b; sur=1; } } for(R int i=1;i<=deep;++i) printf("%lld",c[i]); return 0; }