zoukankan      html  css  js  c++  java
  • L老师讲解的大数问题 2013.5.20

    模板来自吉林大学acm模板及网络。

    老师均添加了一些注释及改进。

    第一个,普通的大数运算:

      1 #include <stdio.h>
      2 #include <string.h>
      3 /*==================================================*\
      4 | 普通的大数运算
      5 \*==================================================*/
      6 const int MAXSIZE = 200;
      7 void Add(char *str1, char *str2, char *str3);
      8 //str3: 和
      9 void Minus(char *str1, char *str2, char *str3);
     10 //要求 str1表示的数比str2的大
     11 void Mul(char *str1, char *str2, char *str3);
     12 //str3: 乘积
     13 void Div(char *str1, char *str2, char *str3, char *str4);
     14 //str3:商  str4:余数
     15 //增加str4, by lyh:13/5/19
     16 int main(void)
     17 {
     18     char str1[MAXSIZE], str2[MAXSIZE], str3[MAXSIZE], str4[MAXSIZE];
     19     while( scanf("%s %s", str1, str2) == 2 )
     20     {
     21         if( strcmp(str1, "0") )
     22         {
     23             memset(str3, '0', sizeof(str3)); // !!!!!
     24             Add(str1, str2, str3);
     25             printf("Add:%s\n", str3);
     26             memset(str3, '0', sizeof(str3));
     27             Minus(str1, str2, str3);
     28             printf("Minus:%s\n", str3);
     29             memset(str3, '0', sizeof(str3));
     30             Mul(str1, str2, str3);
     31             printf("Mul:%s\n", str3);
     32             if (strcmp(str2, "0"))
     33             {//第二个数不为0
     34                 memset(str3, '0', sizeof(str3));
     35                 memset(str4, '0', sizeof(str4));
     36                 Div(str1, str2, str3,str4);
     37                 printf("Div:%s\t%s\n", str3,str4);
     38             }
     39         }
     40         else //第一个数为0的处理
     41         {
     42             if( strcmp(str2, "0") )
     43                 printf("%s\n-%s\n0\n0\t0\n", str2, str2);
     44             else //两个数都为0的处理
     45                 printf("0\n0\n0\n0\t0\n");
     46         }
     47     }
     48     return 0;
     49 }
     50 void Add(char *str1, char *str2, char *str3)
     51 {
     52     // str3 = str1 + str2;
     53     int i, j, i1, i2, tmp, carry;
     54     int len1 = strlen(str1), len2 = strlen(str2);
     55     char ch;
     56     i1 = len1-1;
     57     i2 = len2-1;
     58     j = carry = 0;
     59     for( ; i1 >= 0 && i2 >= 0; ++j, --i1, --i2 )
     60     {
     61         tmp = str1[i1]-'0'+str2[i2]-'0'+carry;
     62         carry = tmp/10;
     63         str3[j] = tmp%10+'0';
     64     }
     65     while( i1 >= 0 )
     66     {
     67         //处理剩余加数1
     68         tmp = str1[i1--]-'0'+carry;
     69         carry = tmp/10;
     70         str3[j++] = tmp%10+'0';
     71     }
     72     while( i2 >= 0 )
     73     {
     74         //处理剩余加数2
     75         tmp = str2[i2--]-'0'+carry;
     76         carry = tmp/10;
     77         str3[j++] = tmp%10+'0';
     78     }
     79     if( carry ) //最高位进位
     80         str3[j++] = carry+'0';
     81     str3[j] = '\0';
     82     for( i=0, --j; i < j; ++i, --j )
     83     {
     84         // 逆序结果
     85         ch = str3[i];
     86         str3[i] = str3[j];
     87         str3[j] = ch;
     88     }
     89 }
     90 void Minus(char *str1, char *str2, char *str3)
     91 {
     92     // str3 = str1-str2 (str1 > str2)
     93     int i, j, i1, i2, tmp, carry;
     94     int len1 = strlen(str1), len2 = strlen(str2);
     95     char ch;
     96     i1 = len1-1;
     97     i2 = len2-1;
     98     j = carry = 0;
     99     while( i2 >= 0 )
    100     {
    101         //处理小数str2
    102         tmp = str1[i1]-str2[i2]-carry;
    103         if( tmp < 0 )
    104         {
    105             str3[j] = tmp+10+'0';
    106             carry = 1;
    107         }
    108         else
    109         {
    110             str3[j] = tmp+'0';
    111             carry = 0;
    112         }
    113         --i1;
    114         --i2;
    115         ++j;
    116     }
    117     while( i1 >= 0 )
    118     {
    119         //处理大数str1的剩余部分
    120         tmp = str1[i1]-'0'-carry;
    121         if( tmp < 0 )
    122         {
    123             str3[j] = tmp+10+'0';
    124             carry = 1;
    125         }
    126         else
    127         {
    128             str3[j] = tmp+'0';
    129             carry = 0;
    130         }
    131         --i1;
    132         ++j;
    133     }
    134     --j;
    135     //删除数字的前导0
    136     while( str3[j] == '0' && j > 0 ) --j;
    137     str3[++j] = '\0';
    138     for( i=0, --j; i < j; ++i, --j )
    139     {
    140         // 逆序结果
    141         ch = str3[i];
    142         str3[i] = str3[j];
    143         str3[j] = ch;
    144     }
    145 }
    146 
    147 void Mul(char *str1, char *str2, char *str3)
    148 {
    149     int i, j, i1, i2, tmp, carry, jj;
    150     int len1 = strlen(str1), len2 = strlen(str2);
    151     char ch;
    152     jj = carry = 0;
    153     // jj 从最后1位向前依次处理每1位
    154 
    155     for( i1=len1-1; i1 >= 0; --i1 )
    156     {
    157         j = jj;  //j从jj开始依次处理每1位
    158         for( i2=len2-1; i2 >= 0; --i2, ++j )
    159         {
    160             tmp = (str3[j]-'0')+(str1[i1]-'0')*(str2[i2]-'0')+carry;
    161             if( tmp > 9 )
    162             {
    163                 carry = tmp/10;
    164                 str3[j] = tmp%10+'0';
    165             }
    166             else
    167             {
    168                 str3[j] = tmp+'0';
    169                 carry = 0;
    170             }
    171         }
    172         if( carry )
    173         {
    174             //最高位进位
    175             str3[j] = carry+'0';
    176             carry = 0;
    177             ++j;
    178         }
    179         ++jj;
    180     }
    181     --j;
    182     //去掉尾部0,即乘法结果的前导0
    183     while( str3[j] == '0' && j > 0 ) --j;
    184     str3[++j] = '\0';
    185     for( i=0, --j; i < j; ++i, --j )
    186     {
    187         ch = str3[i];
    188         str3[i] = str3[j];
    189         str3[j] = ch;
    190     }
    191 }
    192 
    193 void Div(char *str1, char *str2, char *str3,char *str4)
    194 {
    195     int i1, i2, i, j, jj, tag, carry, cf, c[MAXSIZE];
    196     //c 存商
    197     int len1 = strlen(str1), len2 = strlen(str2), lend;
    198     char d[MAXSIZE];
    199     //d  当前被除数,
    200     memset(c, 0, sizeof(c));
    201     memcpy(d, str1, len2);
    202     lend = len2;
    203     j = 0; //商的位数,含前导0
    204     for( i1=len2-1; i1 < len1; ++i1 )
    205     {
    206         //i1:商在原被除数的位置
    207         if( lend < len2 )
    208         {
    209             //被除数位数小于除数位数,扩充被除数位数
    210             d[lend] = str1[i1+1];
    211             c[j] = 0;
    212             ++j;
    213             ++lend;
    214         }
    215         else if( lend == len2 )
    216         {
    217             jj = 1;//被除数与除数位数相同且大于除数
    218             for( i=0; i < lend; ++i )
    219             {
    220                 if( d[i] > str2[i] ) break;
    221                 else if( d[i] < str2[i] )
    222                 {
    223                     jj = 0;
    224                     break;
    225                 }
    226             }
    227             if( jj == 0 )
    228             {
    229                 //被除数小于除数,被除数再扩充一位
    230                 d[lend] = str1[i1+1];
    231                 c[j] = 0;
    232                 ++j;
    233                 ++lend;
    234                 continue;
    235             }
    236         }
    237         if( jj==1 || lend > len2 )
    238         {
    239             //被除数大于除数,或者长度比除数多1位
    240             cf = jj=0;
    241             //cf : 是否可以进行除法
    242             while( d[jj] <= '0' && jj < lend ) ++jj;
    243             //找到被除数的第一个非0数字
    244             if( lend-jj > len2 )
    245                 cf = 1;  //被除数长度大于除数
    246             else if( lend-jj < len2 )
    247                 cf = 0; //被除数长度小于除数
    248             else
    249             {
    250                 //被除数长度等于除数
    251                 i2 = 0;
    252                 cf = 1;
    253                 for( i=jj; i < lend; ++i )
    254                 {
    255                     if( d[i] < str2[i2] )
    256                     {
    257                         //被除数小于除数
    258                         cf = 0;
    259                         break;
    260                     }
    261                     else if( d[i] > str2[i2] )
    262                     {
    263                         break;
    264                     }
    265                     ++i2;
    266                 }
    267             }//else
    268             while( cf )
    269             {
    270                 //被除数大于除数,求被除数/除数的商(商是1位数)
    271                 i2 = len2-1;
    272                 cf = 0;
    273                 for( i=lend-1; i >= lend-len2; --i )
    274                 {
    275                     //从末位向前 被除数-除数
    276                     d[i] = d[i]-str2[i2]+'0';
    277                     if( d[i] < '0' )
    278                     {
    279                         d[i] = d[i]+10;
    280                         carry = 1;
    281                         --d[i-1];
    282                     }
    283                     else carry = 0;
    284                     --i2;
    285                 }
    286                 ++c[j]; //累计可以的(被除数-除数)的次数,即商
    287                 //以下代码与上面部分重复,判断被除数是否大于除数
    288                 jj=0;
    289                 while( d[jj] <= '0' && jj < lend ) ++jj;
    290                 if( lend-jj > len2 ) cf = 1;
    291                 else if( lend-jj < len2 ) cf = 0;
    292                 else
    293                 {
    294                     i2 = 0;
    295                     cf = 1;
    296                     for( i=jj; i < lend; ++i )
    297                     {
    298                         if( d[i] < str2[i2] )
    299                         {
    300                             cf = 0;
    301                             break;
    302                         }
    303                         else if( d[i] > str2[i2] )
    304                         {
    305                             break;
    306                         }
    307                         ++i2;
    308                     }
    309                 }//else
    310             }//while
    311 
    312             jj = 0;
    313             //整理余数,得到新的被除数
    314             while( d[jj] <= '0' && jj < lend ) ++jj;
    315             for( i=0; i < lend-jj; ++i ) d[i] = d[i+jj];
    316             d[i] = str1[i1+1];
    317             lend = i+1;
    318             ++j;
    319         }//if
    320     }//for
    321     i = tag = 0;
    322     while( c[i] == 0 ) ++i;
    323     for( ; i < j; ++i, ++tag ) str3[tag] = c[i]+'0';
    324     str3[tag] = '\0';
    325 //以下内容补充 by lyh:13/5/19
    326 // 数组d 保存余数 
    327     i = tag = 0;
    328     while( d[i] == '0' ) ++i;
    329     while( d[i] != '\0' )
    330         str4[tag++] = d[i++];
    331     str4[tag] = '\0';
    332 //商为0时正确返回
    333     if(str3[0]=='\0')
    334     {
    335         str3[0]='0';
    336         str3[1]='\0';
    337     }
    338 //余数为0时正确返回
    339     if(str4[0]=='\0')
    340     {
    341         str4[0]='0';
    342         str4[1]='\0';
    343     }
    344 }

    代码很长,中间代码有冗余,应该还可以优化。

    这是一位一位的计算。

    第二个,比较高效的大数运算:

      1 #include <stdio.h>
      2 #include <string.h>
      3 /*==================================================*\
      4 
      5  | 比较高效的大数
      6  | < , <= , + , - , * , / , %(修改/的最后一行可得)
      7 
      8 \*==================================================*/
      9 
     10 const int base = 10000;    // (base^2) fit into int
     11 const int width = 4;       // width = log base
     12 const int N  = 1000;       // n *  可表示的最大位数
     13 struct bint
     14 {
     15     int ln, v[N];
     16     bint (int r = 0)   // r应该是字符串!
     17     {
     18         for (ln = 0; r > 0; r /= base) v[ln++] = r % base;
     19     }
     20     bint& operator = (const bint& r)
     21     {
     22         memcpy(this, &r, (r.ln + 1) * sizeof(int));// !
     23         return *this;
     24     }
     25 } ;
     26 
     27 bool operator < (const bint& a, const bint& b)
     28 {
     29     int i;
     30     if (a.ln != b.ln) return a.ln < b.ln;
     31     for (i = a.ln - 1; i >= 0 && a.v[i] == b.v[i]; i--);
     32     return i < 0 ? 0 : a.v[i] < b.v[i];
     33 }
     34 
     35 bool operator <= (const bint& a, const bint& b)
     36 {
     37     return !(b < a);
     38 }
     39 
     40 bint operator + (const bint& a, const bint& b)
     41 {
     42     bint res;
     43     int i, cy = 0;
     44     for (i = 0; i < a.ln || i < b.ln || cy > 0; i++)
     45     {
     46         if (i < a.ln) cy += a.v[i];
     47         if (i < b.ln) cy += b.v[i];
     48         res.v[i] = cy % base;
     49         cy /= base;
     50     }
     51     res.ln = i;
     52     return res;
     53 }
     54 
     55 bint operator - (const bint& a, const bint& b)
     56 {
     57     bint res;
     58     int i, cy = 0;
     59     for (res.ln = a.ln, i = 0; i < res.ln; i++)
     60     {
     61         res.v[i] = a.v[i] - cy;
     62         if (i < b.ln) res.v[i] -= b.v[i];
     63         if (res.v[i] < 0) cy = 1, res.v[i] += base;
     64         else cy = 0;
     65     }
     66         //去掉结果的前导0,同时修正长度
     67     while (res.ln > 0 && res.v[res.ln - 1] == 0) res.ln--;
     68     return res;
     69 }
     70 
     71 bint operator * (const bint& a, const bint& b)
     72 {
     73     bint res;
     74     res.ln = 0;
     75     if (0 == b.ln)
     76     {
     77         res.v[0] = 0;
     78         return res;
     79     }
     80     int i, j, cy;
     81     for (i = 0; i < a.ln; i++)
     82     {
     83         for (j=cy=0; j < b.ln || cy > 0; j++, cy/= base)
     84         {
     85             if (j < b.ln) cy += a.v[i] * b.v[j];
     86             if (i + j < res.ln) cy += res.v[i + j];
     87             if (i + j >= res.ln) res.v[res.ln++] = cy % base;
     88             else res.v[i + j] = cy % base;
     89         }
     90     }
     91     return res;
     92 }
     93 bint operator / (const bint& a, const bint& b)
     94 {    // ! b != 0
     95     bint tmp, mod, res;
     96     int i, lf, rg, mid;
     97     mod.v[0] = mod.ln = 0;
     98     for (i = a.ln - 1; i >= 0; i--)
     99     {
    100         mod = mod * base + a.v[i];
    101                 //试商,找到最大的商
    102         for (lf = 0, rg = base -1; lf < rg; )
    103         {
    104             mid = (lf + rg + 1) / 2;
    105             if (b * mid <= mod) lf = mid;
    106             else rg = mid - 1;
    107         }
    108         res.v[i] = lf; //
    109         mod = mod - b * lf; //余数
    110     }
    111     res.ln = a.ln;
    112     while (res.ln > 0 && res.v[res.ln - 1] == 0) res.ln--;
    113     return res;          // return mod 就是%运算
    114 }
    115 int digits(bint& a)          // 返回位数
    116 {
    117     if (a.ln == 0) return 0;
    118     int l = ( a.ln - 1 ) * 4;
    119         //最高位可能不足4位,需要逐位确定
    120     for (int t = a.v[a.ln - 1]; t; ++l, t/=10) ;
    121     return l;
    122 }
    123 bool read(bint& b, char buf[])  // 读取失败返回0
    124 {
    125     if (1 != scanf("%s", buf)) return 0;
    126     int w, u, ln = strlen(buf);
    127     memset(&b, 0, sizeof(bint));
    128     if ('0' == buf[0] && 0 == buf[1]) return 1;
    129     for (w = 1, u = 0; ln; )
    130     {
    131         u += (buf[--ln] - '0') * w;
    132         if (w * 10 == base)
    133         {
    134             b.v[b.ln++] = u;
    135             u = 0;
    136             w = 1;
    137         }
    138         else w *= 10;
    139     }
    140     if (w != 1) b.v[b.ln++] = u;
    141     return 1;
    142 }
    143 
    144 void write(const bint& v)
    145 {
    146     int i;
    147     printf("%d", v.ln == 0 ? 0 : v.v[v.ln - 1]);
    148     for (i = v.ln - 2; i >= 0; i--)
    149         printf("%04d", v.v[i]);  // ! 4 == width
    150     printf("\n");
    151 }
    152 
    153 int main(){
    154     const int MAXSIZE = 200;
    155     char str1[MAXSIZE];
    156     bint b1,b2,b3,b4;
    157     read(b1, str1);
    158     read(b2, str1);
    159     b3=b1+b2;
    160     write(b3);
    161     b3=b1-b2;
    162     write(b3);
    163     b3=b1*b2;
    164     write(b3);
    165     b3=b1/b2;
    166     write(b3);
    167 
    168     return 0;
    169 }

      与第一个不同的是,每四位每四位的计算,计算的时候不是用字符串计算,而是直接用原来的除法运算,因为原来的一定要快,大数运算的时候能用原来的加减乘除运算就尽量用原来的。为什么划出四位来,因为9999*9999约等于10^8,而int型数据最高不过能储存10^9位数,当然你也可以用64数运算(longlong)。

      另外每四位除法运算的时候是用二分法试商,小学老师教我们的时候能凑出来就凑出来,因为基本一眼就看出来了,而正规的做法应该是不断二分试商,直到上界和下界交叉或等于的时候,那个结果就是正确结果。

     第三个,老师提了一下,思路和第二个差不多,只不过更加细化,加了一些东西,老师说“感觉上更快一些”,名字是《捡来的一个大数模板》,来自网络:

      1 //http://www.cnblogs.com/cj695/archive/2012/07/28/2613678.html
      2 #include <iostream>    
      3 #include <cstring>    
      4 using namespace std;    
      5     
      6 #define DIGIT   4      //四位隔开,即万进制    
      7 #define DEPTH   10000        //万进制    
      8 #define MAX     251    //题目最大位数/4,要不大直接设为最大位数也行 
      9 typedef int bignum_t[MAX+1];    //a[0] 用作临时变量
     10      
     11 /************************************************************************/   
     12 /* 读取操作数,对操作数进行处理存储在数组里                             */   
     13 /************************************************************************/   
     14 int read(bignum_t a,istream&is=cin)    
     15 {    
     16     char buf[MAX*DIGIT+1],ch ;    
     17     int i,j ;    
     18     memset((void*)a,0,sizeof(bignum_t));    
     19     if(!(is>>buf))return 0 ;    
     20 //字符串buf逆序,a[0] 初始化为字符串长度
     21     for(a[0]=strlen(buf),i=a[0]/2-1;i>=0;i--)    
     22     ch=buf[i],buf[i]=buf[a[0]-1-i],buf[a[0]-1-i]=ch ;    
     23 //把数据补足为4(DIGIT)位 ,前面+0
     24     for(a[0]=(a[0]+DIGIT-1)/DIGIT,j=strlen(buf);j<a[0]*DIGIT;buf[j++]='0');    
     25 //将buf中数据每4个一组依次存入a 
     26     for(i=1;i<=a[0];i++)    
     27     for(a[i]=0,j=0;j<DIGIT;j++)    
     28     a[i]=a[i]*10+buf[i*DIGIT-1-j]-'0' ;    
     29 //取掉数字的前导0
     30     for(;!a[a[0]]&&a[0]>1;a[0]--);    
     31     return 1 ;    
     32 }    
     33      
     34 void write(const bignum_t a,ostream&os=cout)    
     35 {    
     36     int i,j ;    
     37 //逆序输出数组 a[],高位在后
     38     for(os<<a[i=a[0]],i--;i;i--)    
     39 //输出每个a[i]的前导0,如果 a[i]=123,输出 0123,补足4位
     40     for(j=DEPTH/10;j;j/=10)    
     41     os<<a[i]/j%10 ;    
     42 }     
     43      
     44 int comp(const bignum_t a,const bignum_t b)    
     45 {    
     46     int i ;    
     47 //长度不相同
     48     if(a[0]!=b[0])     
     49     return a[0]-b[0];    
     50 //从高到低逐位比较
     51     for(i=a[0];i;i--)    
     52     if(a[i]!=b[i])    
     53     return a[i]-b[i];    
     54     return 0 ;    
     55 }    
     56      
     57 int comp(const bignum_t a,const int b)    
     58 {    
     59     int c[12]=    
     60     {    
     61         1     
     62     }    
     63     ;
     64 //把整数 b 转换为 4个一组的万进制存贮      
     65     for(c[1]=b;c[c[0]]>=DEPTH;c[c[0]+1]=c[c[0]]/DEPTH,c[c[0]]%=DEPTH,c[0]++);    
     66 //调用其他重载
     67     return comp(a,c);    
     68 }    
     69      
     70 int comp(const bignum_t a,const int c,const int d,const bignum_t b)    
     71 {    
     72 // 测试 a * c 是否大于b ,d 表示 
     73     int i,t=0,O=-DEPTH*2 ;    
     74     if(b[0]-a[0]<d&&c)    
     75     return 1 ;    
     76     for(i=b[0];i>d;i--)    
     77     {    
     78         t=t*DEPTH+a[i-d]*c-b[i];    
     79         if(t>0)return 1 ;    
     80         if(t<O)return 0 ;    
     81     }    
     82     for(i=d;i;i--)    
     83     {    
     84         t=t*DEPTH-b[i];    
     85         if(t>0)return 1 ;    
     86         if(t<O)return 0 ;    
     87     }    
     88     return t>0 ;    
     89 }    
     90 /************************************************************************/   
     91 /* 大数与大数相加                                                       */   
     92 /************************************************************************/   
     93 void add(bignum_t a,const bignum_t b)    
     94 {    
     95     int i ;    
     96     for(i=1;i<=b[0];i++)    
     97     if((a[i]+=b[i])>=DEPTH)    
     98     a[i]-=DEPTH,a[i+1]++;    
     99     if(b[0]>=a[0])    
    100     a[0]=b[0];    
    101     else    
    102     for(;a[i]>=DEPTH&&i<a[0];a[i]-=DEPTH,i++,a[i]++);    
    103     a[0]+=(a[a[0]+1]>0);    
    104 }    
    105 /************************************************************************/   
    106 /* 大数与小数相加                                                       */   
    107 /************************************************************************/   
    108 void add(bignum_t a,const int b)    
    109 {    
    110     int i=1 ;    
    111     for(a[1]+=b;a[i]>=DEPTH&&i<a[0];a[i+1]+=a[i]/DEPTH,a[i]%=DEPTH,i++);    
    112     for(;a[a[0]]>=DEPTH;a[a[0]+1]=a[a[0]]/DEPTH,a[a[0]]%=DEPTH,a[0]++);    
    113 }    
    114 /************************************************************************/   
    115 /* 大数相减(被减数>=减数)                                               */   
    116 /************************************************************************/   
    117 void sub(bignum_t a,const bignum_t b)    
    118 {    
    119     int i ;    
    120     for(i=1;i<=b[0];i++)    
    121     if((a[i]-=b[i])<0)    
    122     a[i+1]--,a[i]+=DEPTH ;    
    123     for(;a[i]<0;a[i]+=DEPTH,i++,a[i]--);    
    124     for(;!a[a[0]]&&a[0]>1;a[0]--);    
    125 }    
    126 /************************************************************************/   
    127 /* 大数减去小数(被减数>=减数)                                           */   
    128 /************************************************************************/   
    129 void sub(bignum_t a,const int b)    
    130 {    
    131     int i=1 ;    
    132     for(a[1]-=b;a[i]<0;a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH,i++);    
    133     for(;!a[a[0]]&&a[0]>1;a[0]--);    
    134 }    
    135      
    136 void sub(bignum_t a,const bignum_t b,const int c,const int d)    
    137 {    
    138     int i,O=b[0]+d ;    
    139     for(i=1+d;i<=O;i++)    
    140     if((a[i]-=b[i-d]*c)<0)    
    141     a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH ;    
    142     for(;a[i]<0;a[i+1]+=(a[i]-DEPTH+1)/DEPTH,a[i]-=(a[i]-DEPTH+1)/DEPTH*DEPTH,i++);    
    143     for(;!a[a[0]]&&a[0]>1;a[0]--);    
    144 }    
    145 /************************************************************************/   
    146 /* 大数相乘,读入被乘数a,乘数b,结果保存在c[]                          */   
    147 /************************************************************************/   
    148 void mul(bignum_t c,const bignum_t a,const bignum_t b)    
    149 {    
    150     int i,j ;    
    151     memset((void*)c,0,sizeof(bignum_t));    
    152     for(c[0]=a[0]+b[0]-1,i=1;i<=a[0];i++)    
    153     for(j=1;j<=b[0];j++)    
    154     if((c[i+j-1]+=a[i]*b[j])>=DEPTH)    
    155     c[i+j]+=c[i+j-1]/DEPTH,c[i+j-1]%=DEPTH ;    
    156     for(c[0]+=(c[c[0]+1]>0);!c[c[0]]&&c[0]>1;c[0]--);    
    157 }    
    158 /************************************************************************/   
    159 /* 大数乘以小数,读入被乘数a,乘数b,结果保存在被乘数                   */   
    160 /************************************************************************/   
    161 void mul(bignum_t a,const int b)    
    162 {    
    163     int i ;    
    164     for(a[1]*=b,i=2;i<=a[0];i++)    
    165     {    
    166         a[i]*=b ;    
    167         if(a[i-1]>=DEPTH)    
    168         a[i]+=a[i-1]/DEPTH,a[i-1]%=DEPTH ;    
    169     }    
    170     for(;a[a[0]]>=DEPTH;a[a[0]+1]=a[a[0]]/DEPTH,a[a[0]]%=DEPTH,a[0]++);    
    171     for(;!a[a[0]]&&a[0]>1;a[0]--);    
    172 }    
    173      
    174 void mul(bignum_t b,const bignum_t a,const int c,const int d)    
    175 {    
    176     int i ;    
    177     memset((void*)b,0,sizeof(bignum_t));    
    178     for(b[0]=a[0]+d,i=d+1;i<=b[0];i++)    
    179     if((b[i]+=a[i-d]*c)>=DEPTH)    
    180     b[i+1]+=b[i]/DEPTH,b[i]%=DEPTH ;    
    181     for(;b[b[0]+1];b[0]++,b[b[0]+1]=b[b[0]]/DEPTH,b[b[0]]%=DEPTH);    
    182     for(;!b[b[0]]&&b[0]>1;b[0]--);    
    183 }    
    184 /**************************************************************************/   
    185 /* 大数相除,读入被除数a,除数b,结果保存在c[]数组                         */   
    186 /* 需要comp()函数                                                         */   
    187 /**************************************************************************/   
    188 void div(bignum_t c,bignum_t a,const bignum_t b)    
    189 {    
    190     int h,l,m,i ;    
    191     memset((void*)c,0,sizeof(bignum_t));    
    192     c[0]=(b[0]<a[0]+1)?(a[0]-b[0]+2):1 ;    
    193     for(i=c[0];i;sub(a,b,c[i]=m,i-1),i--)    
    194     for(h=DEPTH-1,l=0,m=(h+l+1)>>1;h>l;m=(h+l+1)>>1)    
    195     if(comp(b,m,i-1,a))h=m-1 ;    
    196     else l=m ;    
    197     for(;!c[c[0]]&&c[0]>1;c[0]--);    
    198     c[0]=c[0]>1?c[0]:1 ;    
    199 }    
    200      
    201 void div(bignum_t a,const int b,int&c)    
    202 {    
    203     int i ;    
    204     for(c=0,i=a[0];i;c=c*DEPTH+a[i],a[i]=c/b,c%=b,i--);    
    205     for(;!a[a[0]]&&a[0]>1;a[0]--);    
    206 }    
    207 /************************************************************************/   
    208 /* 大数平方根,读入大数a,结果保存在b[]数组里                           */   
    209 /* 需要comp()函数                                                       */   
    210 /************************************************************************/   
    211 void sqrt(bignum_t b,bignum_t a)    
    212 {    
    213     int h,l,m,i ;    
    214     memset((void*)b,0,sizeof(bignum_t));    
    215     for(i=b[0]=(a[0]+1)>>1;i;sub(a,b,m,i-1),b[i]+=m,i--)    
    216     for(h=DEPTH-1,l=0,b[i]=m=(h+l+1)>>1;h>l;b[i]=m=(h+l+1)>>1)    
    217     if(comp(b,m,i-1,a))h=m-1 ;    
    218     else l=m ;    
    219     for(;!b[b[0]]&&b[0]>1;b[0]--);    
    220     for(i=1;i<=b[0];b[i++]>>=1);    
    221 }    
    222 /************************************************************************/   
    223 /* 返回大数的长度                                                       */   
    224 /************************************************************************/   
    225 int length(const bignum_t a)    
    226 {    
    227     int t,ret ;    
    228     for(ret=(a[0]-1)*DIGIT,t=a[a[0]];t;t/=10,ret++);    
    229     return ret>0?ret:1 ;    
    230 }    
    231 /************************************************************************/   
    232 /* 返回指定位置的数字,从低位开始数到第b位,返回b位上的数               */   
    233 /************************************************************************/   
    234 int digit(const bignum_t a,const int b)    
    235 {    
    236     int i,ret ;    
    237     for(ret=a[(b-1)/DIGIT+1],i=(b-1)%DIGIT;i;ret/=10,i--);    
    238     return ret%10 ;    
    239 }    
    240 /************************************************************************/   
    241 /* 返回大数末尾0的个数                                                  */   
    242 /************************************************************************/   
    243 int zeronum(const bignum_t a)    
    244 {    
    245     int ret,t ;    
    246     for(ret=0;!a[ret+1];ret++);    
    247     for(t=a[ret+1],ret*=DIGIT;!(t%10);t/=10,ret++);    
    248     return ret ;    
    249 }    
    250      
    251 void comp(int*a,const int l,const int h,const int d)    
    252 {    
    253     int i,j,t ;    
    254     for(i=l;i<=h;i++)    
    255     for(t=i,j=2;t>1;j++)    
    256     while(!(t%j))    
    257     a[j]+=d,t/=j ;    
    258 }    
    259      
    260 void convert(int*a,const int h,bignum_t b)    
    261 {    
    262     int i,j,t=1 ;    
    263     memset(b,0,sizeof(bignum_t));    
    264     for(b[0]=b[1]=1,i=2;i<=h;i++)    
    265     if(a[i])    
    266     for(j=a[i];j;t*=i,j--)    
    267     if(t*i>DEPTH)    
    268     mul(b,t),t=1 ;    
    269     mul(b,t);    
    270 }    
    271 /************************************************************************/   
    272 /* 组合数                                                               */   
    273 /************************************************************************/   
    274 void combination(bignum_t a,int m,int n)    
    275 {    
    276     int*t=new int[m+1];    
    277     memset((void*)t,0,sizeof(int)*(m+1));    
    278     comp(t,n+1,m,1);    
    279     comp(t,2,m-n,-1);    
    280     convert(t,m,a);    
    281     delete[]t ;    
    282 }    
    283 /************************************************************************/   
    284 /* 排列数                                                               */   
    285 /************************************************************************/   
    286 void permutation(bignum_t a,int m,int n)    
    287 {    
    288     int i,t=1 ;    
    289     memset(a,0,sizeof(bignum_t));    
    290     a[0]=a[1]=1 ;    
    291     for(i=m-n+1;i<=m;t*=i++)    
    292     if(t*i>DEPTH)    
    293     mul(a,t),t=1 ;    
    294     mul(a,t);    
    295 }    
    296     
    297 #define SGN(x) ((x)>0?1:((x)<0?-1:0))    
    298 #define ABS(x) ((x)>0?(x):-(x))    
    299      
    300 int read(bignum_t a,int&sgn,istream&is=cin)    
    301 {    
    302     char str[MAX*DIGIT+2],ch,*buf ;    
    303     int i,j ;    
    304     memset((void*)a,0,sizeof(bignum_t));    
    305     if(!(is>>str))return 0 ;    
    306     buf=str,sgn=1 ;    
    307     if(*buf=='-')sgn=-1,buf++;    
    308     for(a[0]=strlen(buf),i=a[0]/2-1;i>=0;i--)    
    309     ch=buf[i],buf[i]=buf[a[0]-1-i],buf[a[0]-1-i]=ch ;    
    310     for(a[0]=(a[0]+DIGIT-1)/DIGIT,j=strlen(buf);j<a[0]*DIGIT;buf[j++]='0');    
    311     for(i=1;i<=a[0];i++)    
    312     for(a[i]=0,j=0;j<DIGIT;j++)    
    313     a[i]=a[i]*10+buf[i*DIGIT-1-j]-'0' ;    
    314     for(;!a[a[0]]&&a[0]>1;a[0]--);    
    315     if(a[0]==1&&!a[1])sgn=0 ;    
    316     return 1 ;    
    317 }    
    318 struct bignum     
    319 {    
    320     bignum_t num ;    
    321     int sgn ;    
    322     public :    
    323     inline bignum()    
    324     {    
    325         memset(num,0,sizeof(bignum_t));    
    326         num[0]=1 ;    
    327         sgn=0 ;    
    328     }    
    329     inline int operator!()    
    330     {    
    331         return num[0]==1&&!num[1];    
    332     }    
    333     inline bignum&operator=(const bignum&a)    
    334     {    
    335         memcpy(num,a.num,sizeof(bignum_t));    
    336         sgn=a.sgn ;    
    337         return*this ;    
    338     }    
    339     inline bignum&operator=(const int a)    
    340     {    
    341         memset(num,0,sizeof(bignum_t));    
    342         num[0]=1 ;    
    343         sgn=SGN (a);    
    344         add(num,sgn*a);    
    345         return*this ;    
    346     }    
    347     ;    
    348     inline bignum&operator+=(const bignum&a)    
    349     {    
    350         if(sgn==a.sgn)add(num,a.num);    
    351         else if            
    352         (sgn&&a.sgn)    
    353         {    
    354             int ret=comp(num,a.num);    
    355             if(ret>0)sub(num,a.num);    
    356             else if(ret<0)    
    357             {    
    358                 bignum_t t ;    
    359                 memcpy(t,num,sizeof(bignum_t));    
    360                 memcpy(num,a.num,sizeof(bignum_t));    
    361                 sub (num,t);    
    362                 sgn=a.sgn ;    
    363             }    
    364             else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0 ;    
    365         }    
    366         else if(!sgn)    
    367             memcpy(num,a.num,sizeof(bignum_t)),sgn=a.sgn ;    
    368         return*this ;    
    369     }    
    370     inline bignum&operator+=(const int a)    
    371     {    
    372         if(sgn*a>0)add(num,ABS(a));    
    373         else if(sgn&&a)    
    374         {    
    375             int  ret=comp(num,ABS(a));    
    376             if(ret>0)sub(num,ABS(a));    
    377             else if(ret<0)    
    378             {    
    379                 bignum_t t ;    
    380                 memcpy(t,num,sizeof(bignum_t));    
    381                 memset(num,0,sizeof(bignum_t));    
    382                 num[0]=1 ;    
    383                 add(num,ABS (a));    
    384                 sgn=-sgn ;    
    385                 sub(num,t);    
    386             }    
    387             else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0 ;    
    388         }    
    389         else if    
    390             (!sgn)sgn=SGN(a),add(num,ABS(a));    
    391         return*this ;    
    392     }    
    393     inline bignum operator+(const bignum&a)    
    394     {    
    395         bignum ret ;    
    396         memcpy(ret.num,num,sizeof (bignum_t));    
    397         ret.sgn=sgn ;    
    398         ret+=a ;    
    399         return ret ;    
    400     }    
    401     inline bignum operator+(const int a)    
    402     {    
    403         bignum ret ;    
    404         memcpy(ret.num,num,sizeof (bignum_t));    
    405         ret.sgn=sgn ;    
    406         ret+=a ;    
    407         return ret ;    
    408     }    
    409     inline bignum&operator-=(const bignum&a)    
    410     {    
    411         if(sgn*a.sgn<0)add(num,a.num);    
    412         else if            
    413         (sgn&&a.sgn)    
    414         {    
    415             int ret=comp(num,a.num);    
    416             if(ret>0)sub(num,a.num);    
    417             else if(ret<0)    
    418             {    
    419                 bignum_t t ;    
    420                 memcpy(t,num,sizeof(bignum_t));    
    421                 memcpy(num,a.num,sizeof(bignum_t));    
    422                 sub(num,t);    
    423                 sgn=-sgn ;    
    424             }    
    425             else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0 ;    
    426         }    
    427         else if(!sgn)add (num,a.num),sgn=-a.sgn ;    
    428         return*this ;    
    429     }    
    430     inline bignum&operator-=(const int a)    
    431     {    
    432         if(sgn*a<0)add(num,ABS(a));    
    433         else if(sgn&&a)    
    434         {    
    435             int  ret=comp(num,ABS(a));    
    436             if(ret>0)sub(num,ABS(a));    
    437             else if(ret<0)    
    438             {    
    439                 bignum_t t ;    
    440                 memcpy(t,num,sizeof(bignum_t));    
    441                 memset(num,0,sizeof(bignum_t));    
    442                 num[0]=1 ;    
    443                 add(num,ABS(a));    
    444                 sub(num,t);    
    445                 sgn=-sgn ;    
    446             }    
    447             else memset(num,0,sizeof(bignum_t)),num[0]=1,sgn=0 ;    
    448         }    
    449         else if    
    450             (!sgn)sgn=-SGN(a),add(num,ABS(a));    
    451         return*this ;    
    452     }    
    453     inline bignum operator-(const bignum&a)    
    454     {    
    455         bignum ret ;    
    456         memcpy(ret.num,num,sizeof(bignum_t));    
    457         ret.sgn=sgn ;    
    458         ret-=a ;    
    459         return ret ;    
    460     }    
    461     inline bignum operator-(const int a)    
    462     {    
    463         bignum ret ;    
    464         memcpy(ret.num,num,sizeof(bignum_t));    
    465         ret.sgn=sgn ;    
    466         ret-=a ;    
    467         return ret ;    
    468     }    
    469     inline bignum&operator*=(const bignum&a)    
    470     {    
    471         bignum_t t ;    
    472         mul(t,num,a.num);    
    473         memcpy(num,t,sizeof(bignum_t));    
    474         sgn*=a.sgn ;    
    475         return*this ;    
    476     }    
    477     inline bignum&operator*=(const int a)    
    478     {    
    479         mul(num,ABS(a));    
    480         sgn*=SGN(a);    
    481         return*this ;    
    482     }    
    483     inline bignum operator*(const bignum&a)    
    484     {    
    485         bignum ret ;    
    486         mul(ret.num,num,a.num);    
    487         ret.sgn=sgn*a.sgn ;    
    488         return ret ;    
    489     }    
    490     inline bignum operator*(const int a)    
    491     {    
    492         bignum ret ;    
    493         memcpy(ret.num,num,sizeof (bignum_t));    
    494         mul(ret.num,ABS(a));    
    495         ret.sgn=sgn*SGN(a);    
    496         return ret ;    
    497     }    
    498     inline bignum&operator/=(const bignum&a)    
    499     {    
    500         bignum_t t ;    
    501         div(t,num,a.num);    
    502         memcpy (num,t,sizeof(bignum_t));    
    503         sgn=(num[0]==1&&!num[1])?0:sgn*a.sgn ;    
    504         return*this ;    
    505     }    
    506     inline bignum&operator/=(const int a)    
    507     {    
    508         int t ;    
    509         div(num,ABS(a),t);    
    510         sgn=(num[0]==1&&!num [1])?0:sgn*SGN(a);    
    511         return*this ;    
    512     }    
    513     inline bignum operator/(const bignum&a)    
    514     {    
    515         bignum ret ;    
    516         bignum_t t ;    
    517         memcpy(t,num,sizeof(bignum_t));    
    518         div(ret.num,t,a.num);    
    519         ret.sgn=(ret.num[0]==1&&!ret.num[1])?0:sgn*a.sgn ;    
    520         return ret ;    
    521     }    
    522     inline bignum operator/(const int a)    
    523     {    
    524         bignum ret ;    
    525         int t ;    
    526         memcpy(ret.num,num,sizeof(bignum_t));    
    527         div(ret.num,ABS(a),t);    
    528         ret.sgn=(ret.num[0]==1&&!ret.num[1])?0:sgn*SGN(a);    
    529         return ret ;    
    530     }    
    531     inline bignum&operator%=(const bignum&a)    
    532     {    
    533         bignum_t t ;    
    534         div(t,num,a.num);    
    535         if(num[0]==1&&!num[1])sgn=0 ;    
    536         return*this ;    
    537     }    
    538     inline int operator%=(const int a)    
    539     {    
    540         int t ;    
    541         div(num,ABS(a),t);    
    542         memset(num,0,sizeof (bignum_t));    
    543         num[0]=1 ;    
    544         add(num,t);    
    545         return t ;    
    546     }    
    547     inline bignum operator%(const bignum&a)    
    548     {    
    549         bignum ret ;    
    550         bignum_t t ;    
    551         memcpy(ret.num,num,sizeof(bignum_t));    
    552         div(t,ret.num,a.num);    
    553         ret.sgn=(ret.num[0]==1&&!ret.num [1])?0:sgn ;    
    554         return ret ;    
    555     }    
    556     inline int operator%(const int a)    
    557     {    
    558         bignum ret ;    
    559         int t ;    
    560         memcpy(ret.num,num,sizeof(bignum_t));    
    561         div(ret.num,ABS(a),t);    
    562         memset(ret.num,0,sizeof(bignum_t));    
    563         ret.num[0]=1 ;    
    564         add(ret.num,t);    
    565         return t ;    
    566     }    
    567     inline bignum&operator++()    
    568     {    
    569         *this+=1 ;    
    570         return*this ;    
    571     }    
    572     inline bignum&operator--()    
    573     {    
    574         *this-=1 ;    
    575         return*this ;    
    576     }    
    577     ;    
    578     inline int operator>(const bignum&a)    
    579     {    
    580         return sgn>0?(a.sgn>0?comp(num,a.num)>0:1):(sgn<0?(a.sgn<0?comp(num,a.num)<0:0):a.sgn<0);    
    581     }    
    582     inline int operator>(const int a)    
    583     {    
    584         return sgn>0?(a>0?comp(num,a)>0:1):(sgn<0?(a<0?comp(num,-a)<0:0):a<0);    
    585     }    
    586     inline int operator>=(const bignum&a)    
    587     {    
    588         return sgn>0?(a.sgn>0?comp(num,a.num)>=0:1):(sgn<0?(a.sgn<0?comp(num,a.num)<=0:0):a.sgn<=0);    
    589     }    
    590     inline int operator>=(const int a)    
    591     {    
    592         return sgn>0?(a>0?comp(num,a)>=0:1):(sgn<0?(a<0?comp(num,-a)<=0:0):a<=0);    
    593     }    
    594     inline int operator<(const bignum&a)    
    595     {    
    596         return sgn<0?(a.sgn<0?comp(num,a.num)>0:1):(sgn>0?(a.sgn>0?comp(num,a.num)<0:0):a.sgn>0);    
    597     }    
    598     inline int operator<(const int a)    
    599     {    
    600         return sgn<0?(a<0?comp(num,-a)>0:1):(sgn>0?(a>0?comp(num,a)<0:0):a>0);    
    601     }    
    602     inline int operator<=(const bignum&a)    
    603     {    
    604         return sgn<0?(a.sgn<0?comp(num,a.num)>=0:1):(sgn>0?(a.sgn>0?comp(num,a.num)<=0:0):a.sgn>=0);    
    605     }    
    606     inline int operator<=(const int a)    
    607     {    
    608         return sgn<0?(a<0?comp(num,-a)>=0:1):    
    609         (sgn>0?(a>0?comp(num,a)<=0:0):a>=0);    
    610     }    
    611     inline int operator==(const bignum&a)    
    612     {    
    613         return(sgn==a.sgn)?!comp(num,a.num):0 ;    
    614     }    
    615     inline int operator==(const int a)    
    616     {    
    617         return(sgn*a>=0)?!comp(num,ABS(a)):0 ;    
    618     }    
    619     inline int operator!=(const bignum&a)    
    620     {    
    621         return(sgn==a.sgn)?comp(num,a.num):1 ;    
    622     }    
    623     inline int operator!=(const int a)    
    624     {    
    625         return(sgn*a>=0)?comp(num,ABS(a)):1 ;    
    626     }    
    627     inline int operator[](const int a)    
    628     {    
    629         return digit(num,a);    
    630     }    
    631     friend inline istream&operator>>(istream&is,bignum&a)    
    632     {    
    633         read(a.num,a.sgn,is);    
    634         return  is ;    
    635     }    
    636     friend inline ostream&operator<<(ostream&os,const bignum&a)    
    637     {    
    638         if(a.sgn<0)    
    639             os<<'-' ;    
    640         write(a.num,os);    
    641         return os ;    
    642     }    
    643     friend inline bignum sqrt(const bignum&a)    
    644     {    
    645         bignum ret ;    
    646         bignum_t t ;    
    647         memcpy(t,a.num,sizeof(bignum_t));    
    648         sqrt(ret.num,t);    
    649         ret.sgn=ret.num[0]!=1||ret.num[1];    
    650         return ret ;    
    651     }    
    652     friend inline bignum sqrt(const bignum&a,bignum&b)    
    653     {    
    654         bignum ret ;    
    655         memcpy(b.num,a.num,sizeof(bignum_t));    
    656         sqrt(ret.num,b.num);    
    657         ret.sgn=ret.num[0]!=1||ret.num[1];    
    658         b.sgn=b.num[0]!=1||ret.num[1];    
    659         return ret ;    
    660     }    
    661     inline int length()    
    662     {    
    663         return :: length(num);    
    664     }    
    665     inline int zeronum()    
    666     {    
    667         return :: zeronum(num);    
    668     }    
    669     inline bignum C(const int m,const int n)    
    670     {    
    671         combination(num,m,n);    
    672         sgn=1 ;    
    673         return*this ;    
    674     }    
    675     inline bignum P(const int m,const int n)    
    676     {    
    677         permutation(num,m,n);    
    678         sgn=1 ;    
    679         return*this ;    
    680     }    
    681 };   
    682 int main()    
    683 {       
    684     bignum a,b,c;       
    685     cin>>a>>b;      
    686     cout<<"加法:"<<a+b<<endl;    
    687     cout<<"减法:"<<a-b<<endl;    
    688     cout<<"乘法:"<<a*b<<endl;    
    689     cout<<"除法:"<<a/b<<endl;       
    690     c=sqrt(a);    
    691     cout<<"平方根:"<<c<<endl;    
    692     cout<<"a的长度:"<<a.length()<<endl;    
    693     cout<<"a的末尾0个数:"<<a.zeronum()<<endl<<endl;    
    694     cout<<"组合: 从10个不同元素取3个元素组合的所有可能性为"<<c.C(10,3)<<endl;    
    695     cout<<"排列: 从10个不同元素取3个元素排列的所有可能性为"<<c.P(10,3)<<endl;    
    696     return 0 ;    
    697 }
  • 相关阅读:
    LeetCode 32. 最长有效括号(Longest Valid Parentheses)
    LeetCode 141. 环形链表(Linked List Cycle)
    LeetCode 160. 相交链表(Intersection of Two Linked Lists)
    LeetCode 112. 路径总和(Path Sum)
    LeetCode 124. 二叉树中的最大路径和(Binary Tree Maximum Path Sum)
    LightGBM新特性总结
    sql service 事务与锁
    C#泛型实例详解
    C# 中的委托和事件(详解)
    C# DateTime日期格式化
  • 原文地址:https://www.cnblogs.com/yym2013/p/3089625.html
Copyright © 2011-2022 走看看