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 }
    大菲波数
  • 相关阅读:
    关于.NET Reflector
    Windows Debugging之九
    在IA32如何将程序计数器的值放入到整数寄存器中?
    [陆续添加]计算机网络最最基础的基本概念
    ASCII表
    [翻译文章]我们是如何做到的: 提高SharePoint.Microsoft.com站点的性能
    Windows API是什么?
    寄存器使用惯例
    阅读笔记 了解ASP.NET底层架构 之一
    汇编程序中的返回值
  • 原文地址:https://www.cnblogs.com/Osea/p/12132940.html
Copyright © 2011-2022 走看看