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 }
  • 相关阅读:
    Fedora13下真正能用的源(2015-5-16亲测)
    Shellcoding教程:介绍ASM(译)
    Shellcoding教程:介绍ASM
    ubuntu解决pppoeconf和network-manager冲突时,可能问题的解决方法
    vue_router-link传参
    js_window.postMessage往不同窗口里面发送数据
    iframe_iframe引入其它页面
    css_去掉默认样式
    vue_常用组件install
    js_正则表达式
  • 原文地址:https://www.cnblogs.com/yym2013/p/3089625.html
Copyright © 2011-2022 走看看