zoukankan      html  css  js  c++  java
  • 大数模板

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<conio.h>
      4 #include<stdlib.h>
      5 #include<time.h>
      6 #define N 1000
      7 // 大数模板。。。
      8 class BigNum
      9 {
     10   public:
     11     int s[N];  //存放各位数字,s[0]为符号位,1代表正数,-1代表负数
     12                //数组内高位存高位,123存在里面则为 1 3 2 1 ,第1个 1表示符号
     13     int len;   //长度
     14   public:
     15     BigNum()
     16     {
     17       memset(s,0,sizeof(s));  //初始化全0
     18       s[0]=1;                 //默认正数
     19       len=2;                  //变量初始化为0
     20     }
     21     int in()              //输入
     22     {
     23       char tmp[N];
     24       int flag=scanf("%s",tmp);
     25       *this=tmp;
     26       return flag;
     27     }
     28     void out()            //输出
     29     {
     30       if(s[0]==-1) printf("-");
     31       for(int i=len-1;i>0;i--)
     32         printf("%d",s[i]);
     33     }
     34     void Clear()
     35     {
     36       memset(s,0,sizeof(s));  //初始化全0
     37       s[0]=1;                 //默认正数
     38       len=2;                  //变量初始化为0
     39     }
     40     BigNum Nizhi()            //排除符号位颠倒数组
     41     {
     42       BigNum ans;
     43       ans.s[0]=s[0];
     44       for(int i=1;i<=len/2;i++)
     45       {
     46         ans.s[i]=s[len-i];
     47         ans.s[len-i]=s[i];
     48       }
     49       ans.len=len;
     50       return ans;
     51     }
     52     friend bool operator<(const BigNum &a,const BigNum &b);
     53     friend bool operator>(const BigNum &a,const BigNum &b);
     54     friend bool operator<=(const BigNum &a,const BigNum &b);
     55     friend bool operator>=(const BigNum &a,const BigNum &b);
     56     friend BigNum operator+(BigNum a,BigNum b);
     57     friend void operator+=(BigNum &a,BigNum b);
     58     friend BigNum operator-(BigNum a,BigNum b);
     59     friend void operator-=(BigNum &a,BigNum b);
     60     friend BigNum operator*(BigNum a,BigNum b);
     61     friend void operator*=(BigNum &a,BigNum b);
     62     friend BigNum operator/(BigNum a,BigNum b);
     63     friend void operator/=(BigNum &a,BigNum b);
     64     friend BigNum operator%(BigNum &a,BigNum b);
     65     friend void operator%=(BigNum &a,BigNum b);
     66     friend bool operator==(const BigNum &a,const BigNum &b);
     67     void operator=(const int a);
     68     void operator=(const char *a);
     69     BigNum operator--();
     70     BigNum operator--(int);
     71     BigNum operator++();
     72     BigNum operator++(int);
     73 };
     74 bool operator<(const BigNum &a,const BigNum &b)
     75 {
     76   bool flag;
     77   if(a.s[0]==-1&&b.s[0]==1) return 1;      //如果a为负,b为正,那么a<b
     78   else if(a.s[0]==1&&b.s[0]==-1) return 0; //如果a为正,b为负,那么a>b
     79   else if(a.s[0]==1&&b.s[0]==1) flag=1;    //如果a、b都为正,flag=1,表示a、b大小和符号无关
     80   else flag=0;                             //如果a、b都为负,flag=0,表示a、b大小和符号有关
     81   // flag=1 时,a、b大小和除符号外的数字大小成正比,反之反比
     82   if(a.len>b.len) return !flag; //a的位数多,所以a大,返回0
     83   else if(a.len<b.len) return flag; //a的位数少,所以a小,返回1
     84   else
     85   {
     86     int i=a.len;                    //从最高位开始比
     87     while(i-->1)
     88     {
     89       if(a.s[i]>b.s[i]) return !flag;
     90       else if(a.s[i]<b.s[i]) return flag;
     91     }
     92     return 0;                       //没有差异即相等返回0
     93   }
     94 }
     95 bool operator<=(const BigNum &a,const BigNum &b) //同 <
     96 {
     97   bool flag; // flag=1 表示两者都是正的 =0表示两者都是负的
     98   if(a.s[0]==-1&&b.s[0]==1) return 1;
     99   else if(a.s[0]==1&&b.s[0]==-1) return 0;
    100   else if(a.s[0]==1&&b.s[0]==1) flag=1;
    101   else flag=0;
    102   // flag 表示1 ,!flag 表示0
    103   if(a.len>b.len) return !flag;
    104   else if(a.len<b.len) return flag;
    105   else
    106   {
    107     int i=a.len;
    108     while(i-->1)
    109     {
    110       if(a.s[i]>b.s[i]) return !flag;
    111       else if(a.s[i]<b.s[i]) return flag;
    112     }
    113     return 1;
    114   }
    115 }
    116 bool operator>(const BigNum &a,const BigNum &b)
    117 {
    118   return !(a<=b);
    119 }
    120 bool operator>=(const BigNum &a,const BigNum &b)
    121 {
    122   return !(a<b);
    123 }
    124 bool operator==(const BigNum &a,const BigNum &b)
    125 {
    126   if(a.s[0]==-1&&b.s[0]==1) return 0;
    127   else if(a.s[0]==1&&b.s[0]==-1) return 0;
    128   if(a.len>b.len) return 0;
    129   else if(a.len<b.len) return 0;
    130   else
    131   {
    132     int i=a.len;
    133     while(i-->1)
    134     {
    135       if(a.s[i]>b.s[i]) return 0;
    136       else if(a.s[i]<b.s[i]) return 0;
    137     }
    138     return 1;
    139   }
    140 }
    141 BigNum operator-(BigNum a,BigNum b)
    142 {
    143   BigNum ans;
    144   if(a.s[0]==1&&b.s[0]==-1)      //如果a正,b负,那么等同于a+|b|
    145   {
    146     b.s[0]=1;
    147     return a+b;
    148   }
    149   else if(a.s[0]==-1&&b.s[0]==1) //如果a负,b正,那么等同于-(|a|+b)
    150   {
    151     a.s[0]=1;
    152     ans=a+b;
    153     ans.s[0]=-1;
    154     return ans;
    155   }
    156   else if(a.s[0]==-1&&b.s[0]==-1) //如果a负,b负,那么等同于|b|-|a|
    157   {
    158     a.s[0]=1;
    159     b.s[0]=1;
    160     return b-a;
    161   }
    162   else             //进到这一区域的,a为正,b为正
    163   {
    164     if(a<b)        //如果a<b,那么等同于-(b-a)
    165     {
    166       ans=b-a;
    167       ans.s[0]=-1;
    168     }
    169     else           //进到这一区域a、b为正,且a>b,也就是说减出来的绝对是正数
    170     {
    171       int i=0;
    172       int lm=a.len>b.len?a.len:b.len;  //由于减出来必定是正数,不需要考虑lm-1位<0的情况
    173       for(int i=1;i<lm;i++)
    174       {
    175         int tmp=ans.s[i]+a.s[i]-b.s[i];
    176         if(tmp<0)
    177         {
    178           ans.s[i+1]--;
    179           tmp+=10;
    180         }
    181         ans.s[i]=tmp;
    182       }
    183       while(lm>2)    //清楚高位0,最多清楚到0为止
    184       {
    185         if(ans.s[lm-1]==0) lm--;
    186         else break;
    187       }
    188       ans.len=lm;
    189     }
    190   }
    191   return ans;
    192 }
    193 void operator-=(BigNum &a,BigNum b)
    194 {
    195   a=a-b;
    196 }
    197 BigNum operator+(BigNum a,BigNum b)
    198 {
    199   BigNum ans;
    200   int lm=a.len>b.len?a.len:b.len;
    201   if(a.s[0]*b.s[0]==1)   //如果两者符号位相同
    202   {
    203     ans.s[0]=a.s[0];     //结果符号位与任意一个相同
    204     for(int i=1;i<lm;i++)
    205     {
    206       int tmp=ans.s[i]+a.s[i]+b.s[i];
    207       if(tmp>=10)
    208       {
    209         ans.s[i+1]++;
    210       }
    211       ans.s[i]=tmp%10;
    212     }
    213     if(ans.s[lm]==0) ans.len=lm; //如果最高位没有进位,那么长度不变,否则加1
    214     else ans.len=lm+1;
    215   }
    216   else                           //如果a、b符号不同,可以转化为减法
    217   {
    218     if(a.s[0]==1)
    219     {
    220       b.s[0]=1;
    221       return a-b;
    222     }
    223     else
    224     {
    225       a.s[0]=1;
    226       return b-a;
    227     }
    228   }
    229   return ans;
    230 }
    231 void operator+=(BigNum &a,BigNum b)
    232 {
    233   a=a+b;
    234 }
    235 
    236 BigNum operator*(BigNum a,BigNum b)
    237 {
    238   BigNum ans;
    239   ans.s[0]=a.s[0]*b.s[0];           //乘法和除法的符号位简单处理
    240   for(int i=1;i<a.len;i++)
    241   {
    242     for(int j=1;j<b.len;j++)
    243     {
    244       ans.s[i+j-1]+=a.s[i]*b.s[j];  //先存
    245     }
    246   }
    247   int maxt=a.len+b.len;             //最多位数
    248   for(int i=1;i<maxt;i++)           //处理每个位上的数
    249   {
    250     if(ans.s[i]>=10)
    251     {
    252       ans.s[i+1]+=ans.s[i]/10;
    253       ans.s[i]=ans.s[i]%10;
    254     }
    255   }
    256   int i;
    257   for(i=maxt;i>1;i--)               //处理高位0
    258   {
    259     if(ans.s[i]!=0) break;
    260   }
    261   ans.len=i+1;
    262   return ans;
    263 }
    264 void operator*=(BigNum &a,BigNum b)
    265 {
    266   a=a*b;
    267 }
    268 BigNum operator/(BigNum a,BigNum b)
    269 {
    270   /*
    271     思路: 首先从a的高位往低位数,如果还<b,那么就再加1位,知道>=b,然后遍历1-9,判断此时
    272         合适取值,和平常手动计算思路一样
    273   */
    274   BigNum ans;
    275   ans.s[0]=a.s[0]*b.s[0];
    276   b.s[0]=1;       //中途比较需要
    277   BigNum tmp;     //添位取值
    278   tmp.len=1;      //刚开始为无值,就是说连a的最高位都还没纳入
    279   BigNum zj;      //中间变量,比较时需要,由于数组是倒置的,所以加这一变量
    280   ans.len=1;      //答案还是空的
    281   int j=a.len;    //j固定指向a,不断取值
    282   bool match=1;   //match为0退出循环
    283   while(1)
    284   {
    285     while(1)   //如果还没取够值,就继续加位
    286     {
    287       if(j==1)    //如果a到了符号位,那么可以退出循环了
    288       {
    289         match=0;
    290         break;
    291       }
    292       tmp.s[tmp.len++]=a.s[--j]; //加位,由于开始不好确定位数,所以直接正向不好办
    293       zj=tmp.Nizhi();            //数组颠倒后再去比较
    294       if(b<=zj) break;           //如果b<=zj了,就可以退出了,否则该位为0
    295       ans.s[ans.len++]=0;
    296     }
    297     if(!match) break;            //match为0退出循环
    298     int i;
    299     BigNum r=b;                  //r为最大容许的乘后值
    300     for(i=2;i<=10;i++)
    301     {
    302       BigNum p;
    303       p.s[p.len-1]=i;    //获得 2 - 10 . 赋值过程不符常规,但由于下一步是乘,可以忽略该bug
    304       BigNum u=b*p;      //如果u超过了中间变量,可以退出了,同i应该减1
    305       if(zj<u) break;
    306       r=u;               //乘得的最大数
    307     }
    308     i--;
    309     ans.s[ans.len++]=i;          //逐位求值
    310     zj=zj-r;                     //获得余数
    311     BigNum q;
    312     if(zj==q) zj.len--;          //如果余数为0,那么去掉,不能出现00,不然会出错
    313     tmp=zj.Nizhi();              //重新逆置
    314   }
    315   ans=ans.Nizhi();               //逆置获得答案
    316   while(ans.s[ans.len-1]==0&&ans.len>2) //高位消0
    317   {
    318     ans.len--;
    319   }
    320   return ans;
    321 }
    322 void operator/=(BigNum &a,BigNum b)
    323 {
    324   a=a/b;
    325 }
    326 BigNum operator%(BigNum &a,BigNum b)
    327 {
    328   b.s[0]=1;
    329   BigNum tmp;
    330   tmp.len=1;
    331   BigNum zj;
    332   int j=a.len;
    333   bool match=1;
    334   while(1)
    335   {
    336     while(1)
    337     {
    338       if(j==1)
    339       {
    340         match=0;
    341         break;
    342       }
    343       tmp.s[tmp.len++]=a.s[--j];
    344       zj=tmp.Nizhi();
    345       if(b<=zj) break;
    346     }
    347     if(!match) break;
    348     int i;
    349     BigNum r=b;
    350     for(i=2;i<=10;i++)
    351     {
    352       BigNum p;
    353       p.s[p.len-1]=i;
    354       BigNum u=b*p;
    355       if(zj<u) break;
    356       r=u;
    357     }
    358     i--;
    359     zj=zj-r;
    360     BigNum q;
    361     if(zj==q) zj.len--;
    362     tmp=zj.Nizhi();
    363   }
    364   if(zj.len==1)
    365   {
    366     zj.Clear();
    367   }
    368   return zj;
    369 }
    370 void operator%=(BigNum &a,BigNum b)
    371 {
    372   a=a%b;
    373 }
    374 void BigNum::operator=(int a)
    375 {
    376   Clear();
    377   if(a<0)
    378   {
    379     s[0]=-1;
    380     a=-a;
    381   }
    382   len=1;
    383   while(a)
    384   {
    385     s[len++]=a%10;
    386     a/=10;
    387   }
    388 }
    389 void BigNum::operator=(const char *a)
    390 {
    391   Clear();
    392   if(*a=='-')
    393   {
    394     s[0]=-1;
    395     a++;
    396   }
    397   len=1;
    398   while(*a&&*a=='0') a++;
    399   while(*a)
    400   {
    401     s[len++]=*a-'0';
    402     a++;
    403   }
    404   if(len==1) len=2;
    405   *this=Nizhi();
    406 }
    407 BigNum BigNum::operator--()   //  --a;
    408 {
    409   BigNum tmp;
    410   tmp=-1;
    411   *this+=tmp;
    412   return *this;
    413 }
    414 BigNum BigNum::operator--(int)  // a--;
    415 {
    416   BigNum ans;
    417   ans=*this;
    418   BigNum tmp;
    419   tmp=-1;
    420   *this+=tmp;
    421   return ans;
    422 }
    423 BigNum BigNum::operator++()  // ++a;
    424 {
    425   BigNum tmp;
    426   tmp=1;
    427   *this+=tmp;
    428   return *this;
    429 }
    430 BigNum BigNum::operator++(int)  // a++;
    431 {
    432   BigNum ans;
    433   ans=*this;
    434   BigNum tmp;
    435   tmp=1;
    436   *this+=tmp;
    437   return ans;
    438 }
    439 int main()
    440 {
    441 
    442   return 0;
    443 }
  • 相关阅读:
    底层原理
    No.1
    No.3
    No.0
    php 10进制转62进制,可用于短网址生成
    php实现斐波那契数列
    五种常见的 PHP 设计模式
    PHP利用MySQL保存session
    HTTP相关
    如何优化tomcat配置(从内存、并发、缓存4个方面)优化
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/4944075.html
Copyright © 2011-2022 走看看