AcWing算法基础1.4
高精度
高精度加法,高精度减法,高精度乘低精度,高精度除以低精度,大概平时用的最多的就是这四个,模板有两种(因为我现在不太会用vector,就用数组也写了个,23333)
高精度运算和人工手算差不多,就是模拟人工手算的过程,乘法有点不一样,在下面有提到,大致也是模拟运算
废话不多说,上模板
高精度加法
1 // C = A + B, A >= 0, B >= 0 2 vector<int> add(vector<int> &A, vector<int> &B) 3 { 4 if (A.size() < B.size()) return add(B, A); 5 6 vector<int> C; 7 int t = 0; 8 for (int i = 0; i < A.size(); i ++ ) 9 { 10 t += A[i]; 11 if (i < B.size()) t += B[i]; 12 C.push_back(t % 10); 13 t /= 10; 14 } 15 16 if (t) C.push_back(t); 17 return C; 18 }
高精度减法
1 // C = A - B, 满足A >= B, A >= 0, B >= 0 2 vector<int> sub(vector<int> &A, vector<int> &B) 3 { 4 vector<int> C; 5 for (int i = 0, t = 0; i < A.size(); i ++ ) 6 { 7 t = A[i] - t; 8 if (i < B.size()) t -= B[i]; 9 C.push_back((t + 10) % 10); 10 if (t < 0) t = 1; 11 else t = 0; 12 } 13 14 while (C.size() > 1 && C.back() == 0) C.pop_back(); 15 return C; 16 }
这里高精度减法对于A < B 的情况我们特判下输出个 - 就好了,模板第九行是比较巧的一步,因为我们减一位后 t 的取值范围是(-10,10)t 可能是正数也可能是负数,对于正数我们可以直接拿来用,对于负数要向前面一位进1,相当于把 t 加10,这里写成(t + 10)% 10 就能把两种情况写在一起了
高精度乘低精度
1 // C = A * b, A >= 0, b > 0 2 vector<int> mul(vector<int> &A, int b) 3 { 4 vector<int> C; 5 int t = 0; 6 for (int i = 0; i < A.size() || t; i ++ ) 7 { 8 if (i < A.size()) t += A[i] * b; 9 C.push_back(t % 10); 10 t /= 10; 11 } 12 13 return C; 14 }
乘法和我们人模拟的算有点差别,比如156 * 23 算第一位的时候直接拿6 * 23,然后再拿5 * 23 + 进位,以此类推
高精度除以低精度
1 // A / b = C ... r, A >= 0, b > 0 2 vector<int> div(vector<int> &A, int b, int &r) 3 { 4 vector<int> C; 5 r = 0; 6 for (int i = A.size() - 1; i >= 0; i -- ) 7 { 8 r = r * 10 + A[i]; 9 C.push_back(r / b); 10 r %= b; 11 } 12 reverse(C.begin(), C.end()); 13 while (C.size() > 1 && C.back() == 0) C.pop_back(); 14 return C; 15 }
上面是用vector的模板,对于不会用vector的我,用数组写了个,呃呃呃呃....
高精度加法
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 int add(int a[], int b[]); 7 const int N = 100000 + 10; 8 char x1[N], x2[N]; 9 int a[N], b[N], c[N]; 10 11 int main() 12 { 13 scanf("%s%s",x1,x2); 14 int len1 = strlen(x1), len2 = strlen(x2); 15 for(int i = len1 - 1, j = 0; i >= 0; i --, j ++) 16 a[j] = x1[i] - '0'; 17 for(int i = len2 - 1, j = 0; i >= 0; i --, j ++) 18 b[j] = x2[i] - '0'; 19 20 int id = add(a, b); 21 for(int i = id - 1; i >= 0; i --) 22 printf("%d",c[i]); 23 return 0; 24 //add(a,b); 25 26 } 27 28 int add(int a[], int b[]) 29 { 30 int mx = 0, id = 0; 31 if(strlen(x1) >= strlen(x2)) mx = strlen(x1); 32 else mx = strlen(x2); 33 int t = 0; 34 for(int i = 0; i < mx; i ++) 35 { 36 c[id++] = (a[i] + b[i] + t) % 10; 37 t = (a[i] + b[i] + t) / 10; 38 } 39 if(t) c[id++] = t; 40 return id; 41 }
高精度减法
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 using namespace std; 6 int mun(int a[], int b[]); 7 bool cmp(int a[], int b[]); //用来比较a,b谁大,判断是输出正数还是负数 8 const int N = 100000 + 10; 9 char x[N], y[N]; 10 int a[N], b[N], c[N]; 11 12 int main() 13 { 14 scanf("%s%s",x,y); 15 int lena = strlen(x), lenb = strlen(y); 16 for(int i = lena - 1, j = 0; i >= 0; i --, j ++ ) a[j] = x[i] - '0'; 17 for(int i = lenb - 1, j = 0; i >= 0; i --, j ++ ) b[j] = y[i] - '0'; 18 19 if(cmp(a, b)) cout << "-"; 20 int temp = mun(a, b); 21 for(int i = temp - 1; i >= 0; i -- ) 22 printf("%d",c[i]); 23 return 0; 24 } 25 26 int mun(int a[], int b[]) 27 { 28 if(cmp(a, b)) return (mun(b, a)); 29 30 int t = 0, mx = max(strlen(x), strlen(y)); 31 for(int i = 0; i < mx; i ++ ) 32 { 33 t = a[i] - b[i] + t; 34 c[i] = (t + 10) % 10; 35 if(t < 0) t = -1; 36 else t = 0; 37 } 38 39 int id = mx; 40 for(int i = mx - 1; i > 0; i --) //去除前导零 41 { 42 if(c[i] == 0) id -- ; 43 else break; 44 } 45 return id; //id是数组c的长度 46 } 47 48 bool cmp(int a[], int b[]) 49 { 50 int mx = max(strlen(x), strlen(y)); 51 for(int i = mx - 1; i >= 0; i -- ) 52 { 53 if(a[i] > b[i]) return 0; 54 if(a[i] < b[i]) return 1; 55 } 56 return 0; 57 }
高精度乘法
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 6 using namespace std; 7 int mul(int a[], int b); 8 const int maxa = 100000 + 10; 9 char x[maxa]; 10 int a[maxa], c[maxa], b; 11 12 int main() 13 { 14 scanf("%s%d",x,&b); 15 int lena = strlen(x); 16 for(int i = lena - 1, j = 0; i >= 0; i --, j ++ ) a[j] = x[i] - '0'; 17 18 int id = mul(a, b); 19 for(int i = id - 1; i >= 0; i -- ) 20 cout << c[i]; 21 return 0; 22 } 23 24 int mul(int a[], int b) 25 { 26 int t = 0, id = 0, lena = strlen(x); 27 for(int i = 0; i < lena; i ++ ) 28 { 29 t = a[i] * b + t; 30 c[id++] = t % 10; 31 t = t / 10; 32 } 33 if(t) c[id++] = t; 34 return id; 35 }
高精度除法
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 int div(int b[], int k); 7 const int N = 100000 + 10; 8 string a; 9 int b[N], c[N], k, t; //t是余数 10 11 int main() 12 { 13 cin >> a >> k; 14 for(int i = 0; i < a.size(); i ++ ) b[i] = a[i] - '0'; 15 16 int id = div(b, k); 17 int q = 0; 18 for(int i = 0; i < id - 1; i ++ ) 19 if(c[i] == 0) q ++ ; 20 else break; 21 for(int i = q; i < id; i ++ ) 22 printf("%d",c[i]); 23 printf("\n%d",t); 24 return 0; 25 } 26 27 int div(int b[], int k) 28 { 29 int id = 0; 30 for(int i = 0; i < a.size(); i ++ ) 31 { 32 t = t * 10 + b[i]; 33 c[id++] = t / k; 34 t %= k; 35 } 36 return id; 37 }
输出两行,第一行是商,第二行是余数