大数处理模板

#include
#include
#include
#include
#define N 400//1000位大数
using namespace std;
class BigNum
{
  public:
    int s[N];  //存放各位数字,s[0]为符号位,1代表正数,-1代表负数
               //数组内高位存高位,123存在里面则为 1 3 2 1 ,第1个 1表示符号
    int len;   //长度
  public:
    BigNum()
    {
      memset(s,0,sizeof(s));  //初始化全0
      s[0]=1;                 //默认正数
      len=2;                  //变量初始化为0
    }
    int in()              //输入
    {
      char tmp[N];
      int flag=scanf("%s",tmp);
      *this=tmp;
      return flag;
    }
    void out()            //输出
    {
      if(s[0]==-1) printf("-");
      for(int i=len-1;i>0;i--)
        printf("%d",s[i]);
    }
    void Clear()
    {
      memset(s,0,sizeof(s));  //初始化全0
      s[0]=1;                 //默认正数
      len=2;                  //变量初始化为0
    }
    BigNum Nizhi()            //排除符号位颠倒数组
    {
      BigNum ans;
      ans.s[0]=s[0];
      for(int i=1;i<=len/2;i++)
      {
        ans.s[i]=s[len-i];
        ans.s[len-i]=s[i];
      }
      ans.len=len;
      return ans;
    }
    friend bool operator<(const BigNum &a,const BigNum &b);
    friend bool operator>(const BigNum &a,const BigNum &b);
    friend bool operator<=(const BigNum &a,const BigNum &b);
    friend bool operator>=(const BigNum &a,const BigNum &b);
    friend BigNum operator+(BigNum a,BigNum b);
    friend void operator+=(BigNum &a,BigNum b);
    friend BigNum operator-(BigNum a,BigNum b);
    friend void operator-=(BigNum &a,BigNum b);
    friend BigNum operator*(BigNum a,BigNum b);
    friend void operator*=(BigNum &a,BigNum b);
    friend BigNum operator/(BigNum a,BigNum b);
    friend void operator/=(BigNum &a,BigNum b);
    friend BigNum operator%(BigNum &a,BigNum b);
    friend void operator%=(BigNum &a,BigNum b);
    friend bool operator==(const BigNum &a,const BigNum &b);
    void operator=(const int a);
    void operator=(const char *a);
    BigNum operator--();
    BigNum operator--(int);
    BigNum operator++();
    BigNum operator++(int);
};
/////////////////////////////////////////////////////////////////逻辑//////////////////
bool operator<(const BigNum &a,const BigNum &b)
{
  bool flag;
  if(a.s[0]==-1&&b.s[0]==1) return 1;      //如果a为负,b为正,那么ab
  else if(a.s[0]==1&&b.s[0]==1) flag=1;    //如果a、b都为正,flag=1,表示a、b大小和符号无关
  else flag=0;                             //如果a、b都为负,flag=0,表示a、b大小和符号有关
  // flag=1 时,a、b大小和除符号外的数字大小成正比,反之反比
  if(a.len>b.len) return !flag; //a的位数多,所以a大,返回0
  else if(a.len1)
    {
      if(a.s[i]>b.s[i]) return !flag;
      else if(a.s[i]b.len) return !flag;
  else if(a.len1)
    {
      if(a.s[i]>b.s[i]) return !flag;
      else if(a.s[i](const BigNum &a,const BigNum &b)
{
  return !(a<=b);
}
bool operator>=(const BigNum &a,const BigNum &b)
{
  return !(ab.len) return 0;
  else if(a.len1)
    {
      if(a.s[i]>b.s[i]) return 0;
      else if(a.s[i]b,也就是说减出来的绝对是正数
    {
      int i=0;
      int lm=a.len>b.len?a.len:b.len;  //由于减出来必定是正数,不需要考虑lm-1位<0的情况
      for(int i=1;i2)    //清楚高位0,最多清楚到0为止
      {
        if(ans.s[lm-1]==0) lm--;
        else break;
      }
      ans.len=lm;
    }
  }
  return ans;
}
void operator-=(BigNum &a,BigNum b)
{
  a=a-b;
}
BigNum operator+(BigNum a,BigNum b)
{
  BigNum ans;
  int lm=a.len>b.len?a.len:b.len;
  if(a.s[0]*b.s[0]==1)   //如果两者符号位相同
  {
    ans.s[0]=a.s[0];     //结果符号位与任意一个相同
    for(int i=1;i=10)
      {
        ans.s[i+1]++;
      }
      ans.s[i]=tmp%10;
    }
    if(ans.s[lm]==0) ans.len=lm; //如果最高位没有进位,那么长度不变,否则加1
    else ans.len=lm+1;
  }
  else                           //如果a、b符号不同,可以转化为减法
  {
    if(a.s[0]==1)
    {
      b.s[0]=1;
      return a-b;
    }
    else
    {
      a.s[0]=1;
      return b-a;
    }
  }
  return ans;
}
void operator+=(BigNum &a,BigNum b)
{
  a=a+b;
}

BigNum operator*(BigNum a,BigNum b)
{
  BigNum ans;
  ans.s[0]=a.s[0]*b.s[0];           //乘法和除法的符号位简单处理
  for(int i=1;i=10)
    {
      ans.s[i+1]+=ans.s[i]/10;
      ans.s[i]=ans.s[i]%10;
    }
  }
  int i;
  for(i=maxt;i>1;i--)               //处理高位0
  {
    if(ans.s[i]!=0) break;
  }
  ans.len=i+1;
  return ans;
}
void operator*=(BigNum &a,BigNum b)
{
  a=a*b;
}
BigNum operator/(BigNum a,BigNum b)
{
  /*
    思路: 首先从a的高位往低位数,如果还=b,然后遍历1-9,判断此时
        合适取值,和平常手动计算思路一样
  */
  BigNum ans;
  ans.s[0]=a.s[0]*b.s[0];
  b.s[0]=1;       //中途比较需要
  BigNum tmp;     //添位取值
  tmp.len=1;      //刚开始为无值,就是说连a的最高位都还没纳入
  BigNum zj;      //中间变量,比较时需要,由于数组是倒置的,所以加这一变量
  ans.len=1;      //答案还是空的
  int j=a.len;    //j固定指向a,不断取值
  bool match=1;   //match为0退出循环
  while(1)
  {
    while(1)   //如果还没取够值,就继续加位
    {
      if(j==1)    //如果a到了符号位,那么可以退出循环了
      {
        match=0;
        break;
      }
      tmp.s[tmp.len++]=a.s[--j]; //加位,由于开始不好确定位数,所以直接正向不好办
      zj=tmp.Nizhi();            //数组颠倒后再去比较
      if(b<=zj) break;           //如果b<=zj了,就可以退出了,否则该位为0
      ans.s[ans.len++]=0;
    }
    if(!match) break;            //match为0退出循环
    int i;
    BigNum r=b;                  //r为最大容许的乘后值
    for(i=2;i<=10;i++)
    {
      BigNum p;
      p.s[p.len-1]=i;    //获得 2 - 10 . 赋值过程不符常规,但由于下一步是乘,可以忽略该bug
      BigNum u=b*p;      //如果u超过了中间变量,可以退出了,同i应该减1
      if(zj2) //高位消0
  {
    ans.len--;
  }
  return ans;
}
void operator/=(BigNum &a,BigNum b)
{
  a=a/b;
}
BigNum operator%(BigNum &a,BigNum b)
{
  b.s[0]=1;
  BigNum tmp;
  tmp.len=1;
  BigNum zj;
  int j=a.len;
  bool match=1;
  while(1)
  {
    while(1)
    {
      if(j==1)
      {
        match=0;
        break;
      }
      tmp.s[tmp.len++]=a.s[--j];
      zj=tmp.Nizhi();
      if(b<=zj) break;
    }
    if(!match) break;
    int i;
    BigNum r=b;
    for(i=2;i<=10;i++)
    {
      BigNum p;
      p.s[p.len-1]=i;
      BigNum u=b*p;
      if(zj>=1;
        a=a*a;
    }return ans;
}

int main(){
    BigNum a,b;b=2;
    int t;scanf("%d",&t);
    while(t--){int n;scanf("%d",&n);
        a=swift(b,n);
        a.out();
        printf("\n");
    }
}

 

用了队友打比赛时候的代码。觉得自己也应该备一份,挺有用的。

你可能感兴趣的:(模板)