标签:
1 #include<stdio.h> 2 #include<string.h> 3 #include<conio.h> 4 #include<stdlib.h> 5 #include<time.h> 6 #define N 10000 7 // 大数模板。。。 8 class BigNum 9 { 10 public: 11 int s[N]; //存放各位数字,s[0]为符号位,1代表正数,-1代表负数 12 //数组内高位存高位,123存在里面则为 1 3 2 1 ,第1个 1表示符号 13 int len; //长度 14 public: 15 BigNum() 16 { 17 memset(s,0,sizeof(s)); //初始化全0 18 s[0]=1; //默认正数 19 len=2; //变量初始化为0 20 } 21 void Display() //输出 22 { 23 if(s[0]==-1) printf("-"); 24 for(int i=len-1;i>0;i--) 25 printf("%d",s[i]); 26 } 27 void Sets(char *ts) //赋值(bug 中途不能赋值) 28 { 29 int lts=strlen(ts); //应对输入直接是 Sets("123");的情况,重新申请空间 30 char *t; 31 t=(char *)malloc(sizeof(char)*(lts+1)); 32 strcpy(t,ts); //承接ts字符串 33 Clear(); 34 int lt=strlen(t); //获取字符串长度 35 int flag=1; //如果字符串带负号,flag为1,否则为0 36 if(t[0]==‘-‘) s[0]=-1; //设置符号位 37 else 38 { 39 s[0]=1; 40 flag=0; 41 } 42 int j=0; //字符串高位消0 43 for(int i=flag;i<lt-1;i++) 44 if(t[i]==‘0‘) j++; 45 else break; 46 for(int i=j+flag;i<=lt;i++) 47 { 48 t[i-j]=t[i]; 49 } 50 lt=lt-j; 51 for(int i=lt;i>flag;i--)//如果字符串带负号,那么t[0]要被忽略 52 { 53 s[lt-i+1]=t[i-1]-‘0‘; 54 } 55 len=lt+!flag; //如果字符串不带负号,那么len=lt+1 56 free(t); 57 } 58 void Clear() 59 { 60 memset(s,0,sizeof(s)); //初始化全0 61 s[0]=1; //默认正数 62 len=2; //变量初始化为0 63 } 64 BigNum Nizhi() //除法中用到,排除符号位颠倒数组 65 { 66 BigNum ans; 67 ans.s[0]=s[0]; 68 for(int i=1;i<=len/2;i++) 69 { 70 ans.s[i]=s[len-i]; 71 ans.s[len-i]=s[i]; 72 } 73 ans.len=len; 74 return ans; 75 } 76 friend bool operator<(const BigNum &a,const BigNum &b); 77 friend bool operator>(const BigNum &a,const BigNum &b); 78 friend bool operator<=(const BigNum &a,const BigNum &b); 79 friend bool operator>=(const BigNum &a,const BigNum &b); 80 friend BigNum operator+(BigNum a,BigNum b); 81 friend void operator+=(BigNum &a,BigNum b); 82 friend BigNum operator-(BigNum a,BigNum b); 83 friend void operator-=(BigNum &a,BigNum b); 84 friend BigNum operator*(BigNum a,BigNum b); 85 friend void operator*=(BigNum &a,BigNum b); 86 friend BigNum operator/(BigNum a,BigNum b); 87 friend void operator/=(BigNum &a,BigNum b); 88 friend bool operator==(const BigNum &a,const BigNum &b); 89 }; 90 bool operator<(const BigNum &a,const BigNum &b) 91 { 92 bool flag; 93 if(a.s[0]==-1&&b.s[0]==1) return 1; //如果a为负,b为正,那么a<b 94 else if(a.s[0]==1&&b.s[0]==-1) return 0; //如果a为正,b为负,那么a>b 95 else if(a.s[0]==1&&b.s[0]==1) flag=1; //如果a、b都为正,flag=1,表示a、b大小和符号无关 96 else flag=0; //如果a、b都为负,flag=0,表示a、b大小和符号有关 97 // flag=1 时,a、b大小和除符号外的数字大小成正比,反之反比 98 if(a.len>b.len) return !flag; //a的位数多,所以a大,返回0 99 else if(a.len<b.len) return flag; //a的位数少,所以a小,返回1 100 else 101 { 102 int i=a.len; //从最高位开始比 103 while(i-->1) 104 { 105 if(a.s[i]>b.s[i]) return !flag; 106 else if(a.s[i]<b.s[i]) return flag; 107 } 108 return 0; //没有差异即相等返回0 109 } 110 } 111 bool operator<=(const BigNum &a,const BigNum &b) //同 < 112 { 113 bool flag; // flag=1 表示两者都是正的 =0表示两者都是负的 114 if(a.s[0]==-1&&b.s[0]==1) return 1; 115 else if(a.s[0]==1&&b.s[0]==-1) return 0; 116 else if(a.s[0]==1&&b.s[0]==1) flag=1; 117 else flag=0; 118 // flag 表示1 ,!flag 表示0 119 if(a.len>b.len) return !flag; 120 else if(a.len<b.len) return flag; 121 else 122 { 123 int i=a.len; 124 while(i-->1) 125 { 126 if(a.s[i]>b.s[i]) return !flag; 127 else if(a.s[i]<b.s[i]) return flag; 128 } 129 return 1; 130 } 131 } 132 bool operator>(const BigNum &a,const BigNum &b) 133 { 134 return !(a<=b); 135 } 136 bool operator>=(const BigNum &a,const BigNum &b) 137 { 138 return !(a<b); 139 } 140 bool operator==(const BigNum &a,const BigNum &b) 141 { 142 if(a.s[0]==-1&&b.s[0]==1) return 0; 143 else if(a.s[0]==1&&b.s[0]==-1) return 0; 144 if(a.len>b.len) return 0; 145 else if(a.len<b.len) return 0; 146 else 147 { 148 int i=a.len; 149 while(i-->1) 150 { 151 if(a.s[i]>b.s[i]) return 0; 152 else if(a.s[i]<b.s[i]) return 0; 153 } 154 return 1; 155 } 156 } 157 BigNum operator-(BigNum a,BigNum b) 158 { 159 BigNum ans; 160 if(a.s[0]==1&&b.s[0]==-1) //如果a正,b负,那么等同于a+|b| 161 { 162 b.s[0]=1; 163 return a+b; 164 } 165 else if(a.s[0]==-1&&b.s[0]==1) //如果a负,b正,那么等同于-(|a|+b) 166 { 167 a.s[0]=1; 168 ans=a+b; 169 ans.s[0]=-1; 170 return ans; 171 } 172 else if(a.s[0]==-1&&b.s[0]==-1) //如果a负,b负,那么等同于|b|-|a| 173 { 174 a.s[0]=1; 175 b.s[0]=1; 176 return b-a; 177 } 178 else //进到这一区域的,a为正,b为正 179 { 180 if(a<b) //如果a<b,那么等同于-(b-a) 181 { 182 ans=b-a; 183 ans.s[0]=-1; 184 } 185 else //进到这一区域a、b为正,且a>b,也就是说减出来的绝对是正数 186 { 187 int i=0; 188 int lm=a.len>b.len?a.len:b.len; //由于减出来必定是正数,不需要考虑lm-1位<0的情况 189 for(int i=1;i<lm;i++) 190 { 191 int tmp=ans.s[i]+a.s[i]-b.s[i]; 192 if(tmp<0) 193 { 194 ans.s[i+1]--; 195 tmp+=10; 196 } 197 ans.s[i]=tmp; 198 } 199 while(lm>2) //清楚高位0,最多清楚到0为止 200 { 201 if(ans.s[lm-1]==0) lm--; 202 else break; 203 } 204 ans.len=lm; 205 } 206 } 207 return ans; 208 } 209 void operator-=(BigNum &a,BigNum b) 210 { 211 a=a-b; 212 } 213 BigNum operator+(BigNum a,BigNum b) 214 { 215 BigNum ans; 216 int lm=a.len>b.len?a.len:b.len; 217 if(a.s[0]*b.s[0]==1) //如果两者符号位相同 218 { 219 ans.s[0]=a.s[0]; //结果符号位与任意一个相同 220 for(int i=1;i<lm;i++) 221 { 222 int tmp=ans.s[i]+a.s[i]+b.s[i]; 223 if(tmp>=10) 224 { 225 ans.s[i+1]++; 226 } 227 ans.s[i]=tmp%10; 228 } 229 if(ans.s[lm]==0) ans.len=lm; //如果最高位没有进位,那么长度不变,否则加1 230 else ans.len=lm+1; 231 } 232 else //如果a、b符号不同,可以转化为减法 233 { 234 if(a.s[0]==1) 235 { 236 b.s[0]=1; 237 return a-b; 238 } 239 else 240 { 241 a.s[0]=1; 242 return b-a; 243 } 244 } 245 return ans; 246 } 247 void operator+=(BigNum &a,BigNum b) 248 { 249 a=a+b; 250 } 251 252 BigNum operator*(BigNum a,BigNum b) 253 { 254 BigNum ans; 255 ans.s[0]=a.s[0]*b.s[0]; //乘法和除法的符号位简单处理 256 for(int i=1;i<a.len;i++) 257 { 258 for(int j=1;j<b.len;j++) 259 { 260 ans.s[i+j-1]+=a.s[i]*b.s[j]; //先存 261 } 262 } 263 int maxt=a.len+b.len; //最多位数 264 for(int i=1;i<maxt;i++) //处理每个位上的数 265 { 266 if(ans.s[i]>=10) 267 { 268 ans.s[i+1]+=ans.s[i]/10; 269 ans.s[i]=ans.s[i]%10; 270 } 271 } 272 int i; 273 for(i=maxt;i>1;i--) //处理高位0 274 { 275 if(ans.s[i]!=0) break; 276 } 277 ans.len=i+1; 278 return ans; 279 } 280 void operator*=(BigNum &a,BigNum b) 281 { 282 a=a*b; 283 } 284 BigNum operator/(BigNum a,BigNum b) 285 { 286 /* 287 思路: 首先从a的高位往低位数,如果还<b,那么就再加1位,知道>=b,然后遍历1-9,判断此时 288 合适取值,和平常手动计算思路一样 289 */ 290 BigNum ans; 291 ans.s[0]=a.s[0]*b.s[0]; 292 b.s[0]=1; //中途比较需要 293 BigNum tmp; //添位取值 294 tmp.len=1; //刚开始为无值,就是说连a的最高位都还没纳入 295 BigNum zj; //中间变量,比较时需要,由于数组是倒置的,所以加这一变量 296 ans.len=1; //答案还是空的 297 int j=a.len; //j固定指向a,不断取值 298 bool match=1; //match为0退出循环 299 while(1) 300 { 301 while(1) //如果还没取够值,就继续加位 302 { 303 if(j==1) //如果a到了符号位,那么可以退出循环了 304 { 305 match=0; 306 break; 307 } 308 tmp.s[tmp.len++]=a.s[--j]; //加位,由于开始不好确定位数,所以直接正向不好办 309 zj=tmp.Nizhi(); //数组颠倒后再去比较 310 if(b<=zj) break; //如果b<=zj了,就可以退出了,否则该位为0 311 ans.s[ans.len++]=0; 312 } 313 if(!match) break; //match为0退出循环 314 int i; 315 BigNum r=b; //r为最大容许的乘后值 316 for(i=2;i<=10;i++) 317 { 318 BigNum p; 319 p.s[p.len-1]=i; //获得 2 - 10 . 赋值过程不符常规,但由于下一步是乘,可以忽略该bug 320 BigNum u=b*p; //如果u超过了中间变量,可以退出了,同i应该减1 321 if(zj<u) break; 322 r=u; //乘得的最大数 323 } 324 i--; 325 ans.s[ans.len++]=i; //逐位求值 326 zj=zj-r; //获得余数 327 BigNum q; 328 if(zj==q) zj.len--; //如果余数为0,那么去掉,不能出现00,不然会出错 329 tmp=zj.Nizhi(); //重新逆置 330 } 331 ans=ans.Nizhi(); //逆置获得答案 332 while(ans.s[ans.len-1]==0&&ans.len>2) //高位消0 333 { 334 ans.len--; 335 } 336 return ans; 337 } 338 void operator/=(BigNum &a,BigNum b) 339 { 340 a=a/b; 341 } 342 int main() 343 { 344 345 return 0; 346 }
标签:
原文地址:http://www.cnblogs.com/hchlqlz-oj-mrj/p/4944075.html