算法课-大数专题

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 }
BigInteger + BigInteger

【高精度-高精度】

技术图片
 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 }
BigInteger - BigInteger

【高精度 * int】

技术图片
 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 }
BigInteger * Int

【高精度/int】

技术图片
 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  }
BigInteger / Int

 

介绍一下C++中STL库。

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()  返回字符串所在字符数组的起始地址
仅支持流输入输出 ">>" , "<<" 

 

A - N!

【题意】        
     求解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 }
N!

 

B - 序列

【题意】
    数列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 }
序列

 

C - Integer Inquiry

【题意】
    给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 }
Integer Inquiry

 

D - 大菲波数

【题意】
        求解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(公益交流)

好课资源共享:JVM与GC调优

《英雄编程体验课》第 13 课 | 双指针

专题三-动态规划算法总结

数字中心荣获“厦门大数据安全开放创新应用大赛·交通专题”算法赛一等奖

赵强老师免费公开课第三季:大数据实时计算