算法学习之高精度
我们知道C++最大的整数类型为unsigned long long,而unsigned long long最高只能存储64位整数,当我们遇到了几百位的整数进行运算时,我们不能直接使用c++的数据类型来存储这些整数,这时候就需要一个名为高精度的算法来帮忙运算。
首先我们需要知道,在我们小学的时候就学过列式运算,无论是加减乘除都可以用这个办法。因此,高精度也是通过模拟烈士运算来实现的。
我们以洛谷P1009这道题为例子,来学习高精度是如何实现的。
题目:用高精度计算出 S=1!+2!+3!+⋯+n!,其中n<=50。
观察题目,我们发现这题应该需要两个高精度,分别是加法和乘法。当我们的n>21后,计算出来的n!就会超出unsigned long long的范围,所以我们需要高精度乘法,又是求前n项阶乘之和,则需要使用高精度加法。
所以我们可以模拟一下列式计算,来帮助我们更好的理解高精度加法
我们使用两个数组分别存储大数A和大数B,个位放在数组的第一位。使用整数t来存储每次高位的进位数的大小,t的初始值为0。
例如:123 + 29
A[0] = 3, B[0] = 9,t = A[0] + B[0] = 12
因为t>10,所以我们要向高位进1,并将t对10取余,这时候个位就是2
同理,这时候t = A[1]+B[1]+t = 5,加t是因为进1了,这时候t<10,不需要进1,百位就直接是t。
最后得到答案为152。
下面是高精度加法的代码模板,源于Acwing。
1 vector<int> add(vector<int> &A,vector<int> &B){ 2 vector<int>C; 3 4 int t = 0;//进位 5 6 for(int i=0;i<A.size()||i<B.size();i++){ 7 if(i<A.size()) t+=A[i]; 8 if(i<B.size()) t+=B[i]; 9 C.push_back(t%10); 10 t/=10; 11 } 12 if(t) C.push_back(1);//t>0,进位 13 return C; 14 }
跟高精度加法一样,高精度乘法本质也是模拟列式运算。但是和普通的列式运算不同,我们需要用大数A的每一位数字和整数b相乘,
下面是高精度乘法的代码模板,源于AcWing。
1 vector<int> mul(vector<int> &A,int b){ 2 vector<int>C; 3 4 int t = 0;//进位 5 6 for(int i=0;i<A.size()||t;i++){ 7 if(i<A.size())t = t + A[i] * b; 8 C.push_back(t%10); 9 t/=10; 10 } 11 while(C.size()>1&&C.back()==0) C.pop_back();//去除前导0 12 return C; 13 }
当我们学会了这两种算法之后,上面的那道题就很好解决了。
首先求每一个数的阶乘,然后再把它们相加后输出即可。
以下是我的AC代码,仅供参考。
1 #include <iostream> 2 #include <vector> 3 4 using namespace std; 5 typedef long long ll; 6 7 vector<int> mul(vector<int> &A,int b){ 8 vector<int>C; 9 10 int t = 0; 11 12 for(int i=0;i<A.size()||t;i++){ 13 if(i<A.size())t = t + A[i] * b; 14 C.push_back(t%10); 15 t/=10; 16 } 17 while(C.size()>1&&C.back()==0) C.pop_back(); 18 return C; 19 } 20 21 vector<int> add(vector<int> &A,vector<int> &B){ 22 vector<int>C; 23 24 int t = 0; 25 26 for(int i=0;i<A.size()||i<B.size();i++){ 27 if(i<A.size()) t+=A[i]; 28 if(i<B.size()) t+=B[i]; 29 C.push_back(t%10); 30 t/=10; 31 } 32 if(t) C.push_back(1); 33 return C; 34 } 35 36 int main(){ 37 int n; 38 cin>>n; 39 vector<int>A,B; 40 A.push_back(1); 41 B.push_back(1); 42 for(int i=2;i<=n;i++){ 43 A = mul(A,i); 44 B = add(B,A); 45 } 46 for(int i=B.size()-1;i>=0;i--){ 47 cout<<B[i]; 48 } 49 return 0; 50 }
感谢您的阅读,愿您算法之旅一路顺风。