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 }

输出两行,第一行是商,第二行是余数

posted @ 2019-06-04 13:23  chuyds  阅读(285)  评论(0编辑  收藏  举报