算法课-大数专题
Posted osea
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法课-大数专题相关的知识,希望对你有一定的参考价值。
大数也称为高精度,由于计算机无法存放大于16个字节的数字,并且很多时候我们需要计算大于16个字节的数字时,我们就需要用到高精度,高精度是模拟我们人在计算时如果进行加减乘除四则运算。高精度其实在算法竞赛中经常遇到,如果我遇到高精度题目,我选择Java类中有BigInteger类或者直接用python,正所谓"人生苦短,我选python"。因为C++中没有现成类,需要自己进行封装。但是对于掌握高精度的计算过程,还是需要大家自己动手,丰衣足食。
【高精度+高精度】
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 // C = A + B 5 vector<int> Add( vector<int> &A , vector<int> &B ){ 6 vector<int> C ; 7 //Carry 进位 8 int Carry = 0 ; 9 for( int i = 0 ; i < A.size() || i < B.size() ; i++ ){ 10 if( i < A.size() ) Carry += A[i] ; 11 if( i < B.size() ) Carry += B[i] ; 12 13 C.push_back( Carry % 10 ); 14 Carry /= 10 ; 15 } 16 if( Carry ) C.push_back( Carry ); 17 return C ; 18 } 19 int main() 20 { 21 ios_base:: sync_with_stdio(false); 22 cin.tie(NULL) , cout.tie(NULL) ; 23 24 string a , b ; 25 vector<int> A , B , C ; 26 cin >> a >> b ; 27 // String -> vector<int> 28 for( int i = a.size() - 1 ; i >= 0 ; i -- ) A.push_back( a[i]-‘0‘ ); 29 for( int i = b.size() - 1 ; i >= 0 ; i -- ) B.push_back( b[i]-‘0‘ ); 30 31 // C = A + B 32 C = Add( A , B ) ; 33 for( int i = C.size() - 1 ; i >= 0 ; i -- ){ 34 cout << C[i] ; 35 } 36 cout << endl; 37 return 0; 38 }
1 #include<vector> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 8 using namespace std; 9 10 // 判断 A <= B 11 bool Cmp( vector<int> &A , vector<int> &B ){ 12 //判断1 : 根据长度判断 13 if( A.size() != B.size() ) 14 return A.size() > B.size() ; 15 //判断2 : 既然位数相同那么就比较各位上数字大小 16 for( int i = A.size() - 1 ; i >=0 ; i-- ){ 17 if( A[i] != B[i] ) return A[i] > B[i] ; 18 } 19 //判断3 : 如果全部位上都相等,则返回 "<=" 20 return true; 21 } 22 23 // C = A - B 24 vector<int> Sub( vector<int> & A , vector<int> & B ){ 25 vector<int> C ; 26 // Carry 进位 27 int Carry = 0 ; 28 for(int i = 0 ; i < A.size() ; ++i) 29 { 30 Carry = A[i] - Carry ; 31 if( i < B.size() ) Carry -= B[i] ; 32 33 //保留个位 34 C.push_back( (Carry+10) % 10 ) ; 35 //借位 36 Carry = Carry < 0 ? 1 : 0 ; 37 } 38 //去前导零 39 while( C.back() == 0 && C.size() > 1 ) C.pop_back() ; 40 return C ; 41 } 42 int main() 43 { 44 45 ios_base :: sync_with_stdio(false); 46 cin.tie(NULL) , cout.tie(NULL) ; 47 48 string a , b ; 49 vector<int> A , B , C ; 50 51 cin >> a >> b ; 52 // String -> Vector<int> 53 for( int i = a.size() - 1 ; i >= 0 ; i-- ) A.push_back( a[i] - ‘0‘ ); 54 for( int i = b.size() - 1 ; i >= 0 ; i-- ) B.push_back( b[i] - ‘0‘ ); 55 56 if( Cmp(A,B) ) C = Sub( A , B ); 57 else cout << ‘-‘ , C = Sub( B , A ); 58 for( int i = C.size() - 1 ; i >= 0 ; i-- ) 59 cout << C[i] ; 60 cout << endl ; 61 return 0; 62 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 vector<int> Mul( vector<int> &A , int b ){ 5 vector<int> C ; 6 int Carry = 0; 7 for( int i = 0 ; i < A.size() || Carry ; i ++ ){ 8 if( i < A.size() ) Carry += A[i] * b ; 9 C.push_back( Carry % 10 ); 10 Carry /= 10 ; 11 } 12 return C ; 13 } 14 int main() 15 { 16 ios_base :: sync_with_stdio(false) ; 17 cin.tie(NULL) , cout.tie(NULL) ; 18 string a ; int b ; 19 vector<int> A , C ; 20 cin >> a >> b ; 21 for( int i = a.size() - 1 ; i >= 0 ; i -- ){ 22 A.push_back( a[i] -‘0‘ ) ; 23 } 24 C = Mul( A , b ) ; 25 for( int i = C.size() - 1 ; i >= 0 ; i-- ){ 26 cout << C[i] ; 27 } 28 cout << endl ; 29 return 0 ; 30 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 vector<int> Div( vector<int> & A ,int b , int &r ){ 5 vector<int> C ; 6 r = 0 ; 7 for( int i = A.size() - 1 ; i >= 0 ; i -- ){ 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 } 16 int main() 17 { 18 ios_base :: sync_with_stdio(false) ; 19 cin.tie(NULL) , cout.tie(NULL) ; 20 21 string a ; 22 int b ; 23 cin >> a >> b ; 24 vector< int > A , C ; 25 int r ; 26 for( int i = a.size() - 1 ; i >= 0 ; i -- ){ 27 A.push_back( a[i] - ‘0‘ ) ; 28 } 29 30 C = Div( A , b , r ) ; 31 for( int i = C.size() - 1 ; i >=0 ; i-- ){ 32 cout << C[i] ; 33 } 34 cout << endl << r << endl ; 35 return 0; 36 }
STL库是C++中强而有力的工具库,非常强大,C语言虽然说是最早的高级程序语言,但是每隔3年就会修正一遍。
C++11,C++14,C++17,明年可能就会出C++20,每一年都会从STL库中新增加很多常用的数据结构,还有一些其他语言汇总特有的语法也会更新。
其中Vector,String是上面所见到的STL库最常用的库。
vector名字叫“不定长数组”,其特性为自动追加长度。
其作用和Java中或者 C#中的Array类异曲同工.
#include<vector> vector, 变长数组,倍增的思想 size() 返回元素个数 empty() 返回是否为空 clear() 清空 front()/back() push_back()/pop_back() begin()/end() []
String类,真的就是Java和C#中的string 一模一样
#include<string> string,字符串 size()/length() 返回字符串长度 empty() clear() substr(起始下标,(子串长度)) 返回子串 c_str() 返回字符串所在字符数组的起始地址 仅支持流输入输出 ">>" , "<<"
【题意】 求解N! 【题解】 高精度 * int模板,过程中控制4位。 俗称压位高精度 用数组存放时,我们习惯一位一位存放在[0][1][2]…… 但是压位就是,连续四位四位存放在[0][1][2]…… 也就是说十进制变成万进制了。 进位时衡量的单位由 "10" -> "10000" 这样大大降低时间复杂度和空间复杂度。具体直接看代码即可
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N = 1e5 + 10; 5 const int mod = 1e4 ; 6 int a[N] ; 7 int main() 8 { 9 int n ; 10 while( ~scanf("%d",&n) ){ 11 int cnt = 0 ; 12 memset( a , 0 , sizeof a ); 13 a[0] = 1 ; 14 15 for( int i = 1 ; i <= n ; i++ ){ 16 for( int j = 0 ; j <= cnt ; j ++ ){ 17 a[j] = a[j] * i ; 18 if( j > 0 && a[j-1] >= mod ){ 19 a[j] += a[j-1] / mod ; 20 a[j-1] %= mod ; 21 } 22 if( a[cnt] >= mod ) cnt ++ ; 23 } 24 } 25 printf("%d",a[cnt]); 26 for( int i = cnt-1 ; i >= 0 ; i-- ){ 27 printf("%04d",a[i]); 28 } 29 puts(""); 30 } 31 return 0; 32 }
【题意】 数列A满足An = An-1 + An-2 + An-3, n >= 3 编写程序,给定A0, A1 和 A2, 计算A99 【题解】 请套用【高精度+高精度】模板即可
1 #include<cstdio> 2 #include<vector> 3 #include<string> 4 #include<iostream> 5 6 using namespace std; 7 const int N = 1e5+10; 8 9 vector<int> Add( vector<int> &A ,vector<int> &B ){ 10 vector<int> C ; 11 int Carry = 0 ; 12 for( int i = 0 ; i < A.size() || i < B.size() ; i++ ){ 13 if( i < A.size() ) Carry += A[i] ; 14 if( i < B.size() ) Carry += B[i] ; 15 16 C.push_back( Carry % 10 ); 17 Carry /= 10; 18 } 19 if( Carry ) C.push_back( Carry ); 20 return C ; 21 } 22 int main() 23 { 24 string s0 , s1 , s2 ; 25 vector<int> f0 , f1 , f2 , tmp ; 26 while(cin >> s0 >> s1 >> s2){ 27 f0.clear(); 28 f1.clear(); 29 f2.clear(); 30 tmp.clear(); 31 for( int i = s0.size() - 1 ; i >= 0 ; i-- ) f0.push_back( s0[i] - ‘0‘ ); 32 for( int i = s1.size() - 1 ; i >= 0 ; i-- ) f1.push_back( s1[i] - ‘0‘ ); 33 for( int i = s2.size() - 1 ; i >= 0 ; i-- ) f2.push_back( s2[i] - ‘0‘ ); 34 for( int i = 3 ; i <= 99 ; i++ ){ 35 tmp = Add(f1,f2); 36 tmp = Add(tmp,f0); 37 f0 = f1 ; 38 f1 = f2 ; 39 f2 = tmp ; 40 } 41 for( int i = f2.size() - 1 ; i >= 0 ; i-- ){ 42 cout << f2[i] ; 43 } 44 cout << endl ; 45 } 46 return 0; 47 }
【题意】 给T组样例 多组输入的大整数进行相加,每组事例以"0"结尾 【题解】 请套用【高精度+高精度】即可
1 #include<cstdio> 2 #include<vector> 3 #include<string> 4 #include<iostream> 5 6 using namespace std; 7 vector<int> Add( vector<int> &A ,vector<int> &B ){ 8 vector<int> C ; 9 int Carry = 0 ; 10 for( int i = 0 ; i < A.size() || i < B.size() ; i++ ){ 11 if( i < A.size() ) Carry += A[i] ; 12 if( i < B.size() ) Carry += B[i] ; 13 14 C.push_back( Carry % 10 ); 15 Carry /= 10; 16 } 17 if( Carry ) C.push_back( Carry ); 18 return C ; 19 } 20 int main() 21 { 22 string s ; 23 int T ; 24 scanf("%d",&T); 25 while(T--){ 26 vector<int> Ans , x ; 27 Ans.push_back(0); 28 while( cin >> s ){ 29 x.clear(); 30 for( int i = s.size() - 1 ; i >= 0 ; i-- ) 31 x.push_back(s[i]-‘0‘); 32 if( x.size() == 1 && x[0] == 0 ) break; 33 Ans = Add( Ans , x ); 34 } 35 36 while( Ans.size() > 1 && Ans[Ans.size()-1] == 0 ) Ans.pop_back(); 37 for( int i = Ans.size() - 1 ; i >= 0 ; i-- ){ 38 cout << Ans[i] ; 39 } 40 cout << endl ; 41 if( T ){ 42 cout << endl ; 43 } 44 } 45 return 0; 46 }
【题意】
求解fibonacci前1000项
【题解】
请套用【高精度+高精度】即可
1 #include<cstdio> 2 #include<vector> 3 #include<string> 4 #include<iostream> 5 6 using namespace std; 7 const int N = 1e3+10; 8 vector<int> Fib[N] ; 9 vector<int> Add( vector<int> &A ,vector<int> &B ){ 10 vector<int> C ; 11 int Carry = 0 ; 12 for( int i = 0 ; i < A.size() || i < B.size() ; i++ ){ 13 if( i < A.size() ) Carry += A[i] ; 14 if( i < B.size() ) Carry += B[i] ; 15 16 C.push_back( Carry % 10 ); 17 Carry /= 10; 18 } 19 if( Carry ) C.push_back( Carry ); 20 return C ; 21 } 22 void Init(){ 23 Fib[1].push_back(1); 24 Fib[2].push_back(1); 25 for( int i = 3 ; i <= 1000 ; i++ ){ 26 Fib[i] = Add( Fib[i-1] , Fib[i-2] ); 27 } 28 } 29 int main() 30 { 31 Init(); 32 int n ; 33 cin >> n ; 34 for( int i = 0 , x ; i < n ; i++ ){ 35 scanf("%d",&x); 36 for( int i = Fib[x].size() - 1 ; i >= 0 ; i-- ){ 37 cout << Fib[x][i] ; 38 } 39 cout << endl ; 40 } 41 return 0; 42 }
以上是关于算法课-大数专题的主要内容,如果未能解决你的问题,请参考以下文章
必学!二分查找(微课+PPT)|获奖微课算法专题13-6(公益交流)