zoukankan      html  css  js  c++  java
  • 算法课-大数专题

    简介

      大数也称为高精度,由于计算机无法存放大于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 }
    大菲波数
  • 相关阅读:
    左偏树
    论在Windows下远程连接Ubuntu
    ZOJ 3711 Give Me Your Hand
    SGU 495. Kids and Prizes
    POJ 2151 Check the difficulty of problems
    CodeForces 148D. Bag of mice
    HDU 3631 Shortest Path
    HDU 1869 六度分离
    HDU 2544 最短路
    HDU 3584 Cube
  • 原文地址:https://www.cnblogs.com/Osea/p/12132940.html
Copyright © 2011-2022 走看看