解题报告 ch1 大数问题

424 - Integer Inquiry
  //1.大数加法
  两个数a,b相加, 需要记录进位g,
  result的每一位 等于 a与b对应位相加再加上g






10106 - Product
  //1.大数乘法
  a,b相乘
  result 的位数 等于 a.len+b.len 最后去除前缀0
  result.s[i+j] = a.s[i] * b.s[j];
  result.s[i+j+1] = result.s[i+j]/10;
  result.s[i+j] %= 10;




465 - Overflow
  //1.大数比较
  a,b首先比位数
  然后从最大位往下逐位比较
  //2. <climits> 中定义了许多常量
  INT_MAX






748 - Exponentiation
  //大浮点数
  多记录一个小数点位置dot
  消除前缀0   ,整体len减
  消除后缀0   ,数组整体移动,len减,dot也得减


{  
  包含的函数
   1. 消除前缀后缀0
   2. 从string 获取输入
   3. 乘法
   4. 乘方
   5. str() 
 }




10494 - If We Were a Child Again
  //1.大数 减法(只在 a>b下 适用)
  c=a-b
  长度先等于a.len
  然后各个位相减,记录borrow位
  最后消除前缀0


  //2.大数 的各种比较
  利用 >  做各种变换即可


  //3.大数除法
  c=a/b
  长度先等于a.len;
  借助一个bign helper;
  helper = helper * 10 + a.s[i]
  if (helper>b){...}
  else c.s[i]=0;
  最后消除前缀0;


  //4.大数取模
  c=a%b;

  ======>   c = a - a/b *a;



//大数模版
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>

using namespace std;

const int MAXN=1000;

struct bign{
  int len, s[MAXN];

  bign(){ memset(s, 0, sizeof(s)); len=1; }
  bign(int a){ *this = a;}
  bign(const string &a) {*this = a;}
  
  bign operator= (const string &a){
    len = a.size();
    for (int i=0; i<len; ++i)  s[len-1-i]=a[i]-'0';
    for (; len>1 && !s[len-1]; --len);
    return *this;
  }
  
  bign operator= (int a){
    char str[20];
    sprintf(str, "%d", a);
    *this = string(str);
    return *this;
  }

  bign operator+ (const bign &a) const{
    bign c;
    int g=0,digit=0;
    c.len=0;

    for (int i=0; g||i<max(len,a.len); ++i){
      digit = g;
      if (i<len) digit += s[i];
      if (i<a.len) digit += a.s[i];
      c.s[c.len++] = digit%10;
      g = digit/10;  
    }
    return c;
  }


  //只在被减数大于减数的情况下才适合
  bign operator- (const bign &a) const{
    bign c;
    c.len = len;
    int digit = 0, borrow=0;
    for (int i=0; i<len; ++i){
      digit = s[i]-borrow;
      borrow = 0;

      if (i<a.len)  digit = digit - a.s[i];

      if (digit<0){
        digit +=10;
        borrow =1;
      }
      c.s[i]=digit;
    }
    for (;c.len>1 && !c.s[c.len-1]; --c.len);
    return c;
  }

  bign operator* (const bign &a) const{
    bign c;
    c.len = len+a.len;
    
    for (int i=0; i<len; ++i){
      for (int j=0; j<a.len; ++j){
        c.s[i+j] += s[i]*a.s[j];
      }
    } 
  
    for (int i=0; i<c.len; ++i){
      c.s[i+1] +=c.s[i]/10;
      c.s[i] = c.s[i] % 10;
    }

    //记录真实位数,消除前缀0
    for (; c.len>1 && !c.s[c.len-1]; --c.len);
    return c;
  }
  
  bool operator< (const bign &a) const{
    if (len!=a.len) return len<a.len;
    for (int i=len-1; i>=0; --i){
      if (s[i]!=a.s[i])
        return s[i]<a.s[i];
    }
    return false;
  }

  bool operator> (const bign &a) const{
    return a < *this;
  }

  bool operator<= (const bign &a) const{
    return !(a<*this);
  }

  bool operator>= (const bign &a) const{
    return !(*this<a);
  }
  
  bign operator/ (const bign &a) const{
    bign c,helper;
    c.len = len;
    helper = 0;
    for (int i=len-1; i>=0; --i){
      helper = helper*10 + s[i];
      if (helper >= a){
        int j=2;
        for (; j<=9; ++j){  
          if (helper < a*j)
            break;
        }
        j = j-1;
        c.s[i] = j;
        helper = helper - a*j;
      }
      else{
        c.s[i]=0;
      }
    }    
    for (; c.len>1 && !c.s[c.len-1]; --c.len);
    return c;
  }

  bign operator% (const bign &a) const{
    bign c;
    c = (*this) - (*this)/a * a;
    return c;
  }



  string str() const{
    string a="";
    for (int i=0; i<len; ++i)
      a = (char)(s[i]+'0')+a;
    if (a=="")
      a="0";
    return a;
  }
  
};

istream& operator >> (istream &in, bign &x){
  string temp;
  in>>temp;
  x = temp;
  return in;
}

ostream& operator << (ostream &out, const bign &x){
  out<<x.str();
  return out;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值