模板来自吉林大学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 * width: 可表示的最大位数 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 }