ZOJ有很多与大数相关的题目,干脆写了一个比较完整的大数类一次性解决,基本思想很简单,不多解释,代码如下:
Code
1#ifndef BIG_INTEGER
2#define BIG_INTEGER
3
4#include "assert.h"
5#include <vector>
6using namespace std;
7
8class BigInteger
9{
10private:
11 // char is for performance concern
12 // data is sort from lowest bit to large bit
13 // for example, 123 is store as 321
14 vector<char> value;
15 bool isMinus;
16
17 // private constructor, for inner use only
18 BigInteger(vector<char> & v, bool isMinus)
19 {
20 this->isMinus = isMinus;
21 value = v;
22 }
23
24 // remove the 0 at the front
25 void Trim()
26 {
27 vector<char>::reverse_iterator ite;
28
29 ite = value.rbegin();
30 while(value.size() > 0 && (*ite) == '0')
31 {
32 value.pop_back();
33 ite = value.rbegin();
34 }
35
36 // if no value here, it's 0
37 if(value.size() == 0)
38 value.push_back('0');
39 }
40public:
41 // Default Constructor
42 BigInteger()
43 {
44 value.push_back('0');
45 isMinus = false;
46 }
47
48 // int constructor
49 BigInteger(int val)
50 {
51 isMinus = val < 0;
52 do
53 {
54 char c = (char)(val % 10 + '0');
55 value.push_back(c);
56 if(val == 0) // if val is 0
57 break;
58 val /= 10;
59 }while(val != 0);
60 }
61
62 // string constructor
63 BigInteger(string s)
64 {
65 int length = s.length();
66 for(int i = length - 1; i >= 0; --i)
67 {
68 value.push_back(s.at(i));
69 }
70 isMinus = length > 0 && s.at(0) == '-';
71 if(isMinus)
72 // pop up the '-' sign
73 value.pop_back();
74 }
75
76 // == operator
77 bool operator==(const BigInteger & right) const
78 {
79 if(this->Length() != right.Length() || this->isMinus != right.isMinus)
80 return false;
81
82 int length = this->Length();
83 for(int i = 0; i < length; ++i)
84 {
85 if(this->operator [](i) != right[i])
86 return false;
87 }
88 return true;
89 }
90
91 // != operator
92 bool operator!=(const BigInteger & right) const
93 {
94 return !(*this == right);
95 }
96
97 // > operator
98 bool operator>(const BigInteger & right) const
99 {
100 if(!this->isMinus && right.isMinus)
101 return true;
102 else if(this->isMinus && !right.isMinus)
103 return true;
104 else
105 {
106 assert(this->isMinus == right.isMinus);
107
108 // if it's non-negative
109 if(!this->isMinus)
110 {
111 if(this->Length() > right.Length())
112 return true;
113 else if(this->Length() < right.Length())
114 return false;
115 }
116 else
117 {
118 if(this->Length() > right.Length())
119 return false;
120 else if(this->Length() < right.Length())
121 return true;
122 }
123 }
124
125 // if two numbers are the same length
126 int length = this->Length();
127 for(int i = length - 1; i >= 0; --i)
128 {
129 if(this->operator [](i) > right[i])
130 return true;
131 else if(this->operator [](i) < right[i])
132 return false;
133 }
134 assert(*this == right);
135 return false;
136 }
137
138 bool operator>=(const BigInteger & right) const
139 {
140 return *this > right || *this == right;
141 }
142
143 bool operator<(const BigInteger & right) const
144 {
145 return right > *this;
146 }
147
148 // operator +
149 // add two numbers one bit by one
150 BigInteger operator+(const BigInteger & right) const
151 {
152 bool both_minus = false;
153
154 if(right.isMinus || this->isMinus)
155 {
156 // if two numbers both are negative
157 if(right.isMinus && this->isMinus)
158 {
159 both_minus = true;
160 }
161 // if right operand is positive while left operand is negative
162 // for example, (-3) + 5
163 // delegate to 5 - 3
164 else if(!right.isMinus)
165 {
166 assert(this->isMinus == true);
167 BigInteger copy_this(*this);
168 copy_this.isMinus = false;
169 return right - copy_this;
170 }
171 // if left operand is positive while right operand is negative
172 // for example, 5 + (-3) delegate to 5 - 3
173 else
174 {
175 assert(!this->isMinus);
176 BigInteger copy_right(right);
177 copy_right.isMinus = false;
178 return this->operator -(copy_right);
179 }
180 }
181
182 // now two numbers are the same flag, both negative or both positive
183 vector<char> result;
184
185 int min_length, max_length;
186 BigInteger longer_integer;
187
188 if(this->Length() > right.Length())
189 {
190 min_length = right.Length();
191 max_length = this->Length();
192 longer_integer = *this;
193 }
194 else
195 {
196 min_length = this->Length();
197 max_length = right.Length();
198 longer_integer = right;
199 }
200
201 int temp, i, add_one = 0;
202
203 // add the result one bit by one
204 for(i = 0; i < min_length; ++i)
205 {
206 temp = this->operator [](i) + right[i] + add_one;
207
208 add_one = temp > 9 ? 1 : 0;
209 temp %= 10;
210
211 result.push_back((char)(temp + '0'));
212 }
213
214 // while we have more add_one or the left number we have to copy them
215 while(add_one || i < max_length)
216 {
217 if(i >= max_length)
218 assert(add_one == 1);
219
220 temp = i < max_length ? longer_integer[i] + add_one : add_one;
221
222 add_one = temp > 9 ? 1 : 0;
223 temp %= 10;
224
225 result.push_back((char)(temp + '0'));
226
227 ++i;
228 }
229 return BigInteger(result, both_minus);
230 }
231
232 // operator -
233 // substract it one by one
234 BigInteger operator-(const BigInteger & right) const
235 {
236 if(right.isMinus || this->isMinus)
237 {
238 // if both left & right operand are negative
239 // for example, (-5) - (-3) delegate to 3 + (-5)
240 if(this->isMinus && right.isMinus)
241 {
242 BigInteger copy_right(right);
243 copy_right.isMinus = false;
244 return copy_right + *this;
245 }
246 // if left operand is negative while right operand is positive
247 // for example, (-5) - 3, delegate to (-5) + (-3)
248 else if(!right.isMinus)
249 {
250 assert(this->isMinus);
251 BigInteger copy_right(right);
252 copy_right.isMinus = true;
253 return *this + copy_right;
254 }
255 // if left operand is positive while right operand is negative
256 // for example, 5 - (-3), delegate to 5 + 3
257 else
258 {
259 assert(!this->isMinus);
260 BigInteger copy_right(right);
261 copy_right.isMinus = false;
262 return *this + copy_right;
263 }
264 }
265
266 // now we come to M - N while both M,N are positive
267 vector<char> result;
268
269 int min_length, max_length;
270 BigInteger bigger_integer, smaller_integer;
271
272 // return 0 if they're equal :)
273 if(*this == right)
274 {
275 return BigInteger(0);
276 }
277 else if(*this > right)
278 {
279 bigger_integer = *this;
280 smaller_integer = right;
281 }
282 else if(*this < right)
283 {
284 bigger_integer = right;
285 smaller_integer = *this;
286 }
287
288 max_length = bigger_integer.Length();
289 min_length = smaller_integer.Length();
290
291 assert(max_length >= min_length);
292
293 int temp, i, borrow_one = 0;
294
295 // substract them one bit by one
296 for(i = 0; i < min_length; ++i)
297 {
298 temp = bigger_integer[i] + borrow_one - smaller_integer[i];
299
300 borrow_one = temp < 0 ? -1 : 0;
301 temp = (temp + 10) % 10;
302
303 result.push_back((char)(temp + '0'));
304 }
305
306 // while we have more bits to copy
307 while(i < max_length)
308 {
309 temp = bigger_integer[i] + borrow_one;
310
311 borrow_one = temp < 0 ? -1 : 0;
312 temp = (temp + 10) % 10;
313
314 result.push_back((char)(temp + '0'));
315
316 ++i;
317 }
318
319 // make sure we haven't got loan any more
320 assert(borrow_one == 0);
321
322 BigInteger integer = BigInteger(result, bigger_integer == right);
323 integer.Trim();
324 return integer;
325 }
326
327 // operator *
328 // Key Algorithm:
329 // C[i + j] += A[i] + b[j]
330 BigInteger operator*(const BigInteger & right) const
331 {
332 int left_length = this->Length();
333 int right_length = right.Length();
334
335 vector<int> v(left_length + right_length);
336
337 for(int i = 0; i < left_length + right_length; ++i)
338 {
339 v[i] = 0;
340 }
341
342 // calculate the result
343 for(int i = 0; i < left_length; ++i)
344 {
345 for(int j = 0; j < right_length; ++j)
346 {
347 v[i + j] += this->operator[] (i) * right[j];
348 }
349 }
350
351 // parse result base on 10
352 vector<char> result;
353 vector<int>::iterator end = v.end();
354 for(vector<int>::iterator ite = v.begin(); ite != end; ++ite)
355 {
356 result.push_back((char)((*ite) % 10 + '0'));
357
358 if(ite + 1 != end)
359 {
360 (*(ite + 1)) += (*ite) / 10;
361 }
362 else
363 {
364 assert((*ite) < 10);
365 }
366 }
367
368 BigInteger r = BigInteger(result, this->isMinus || right.isMinus);
369 r.Trim();
370 return r;
371 }
372
373 // operator /
374 // simulate the divide operation
375 BigInteger operator/(const BigInteger & right) const
376 {
377 if(right == BigInteger(0)
378 throw new exception("Divide by Zero.");
379 // specify judgement
380 if(*this < right)
381 return BigInteger(0);
382 if(*this == right)
383 return BigInteger(1);
384
385 BigInteger temp(0);
386 BigInteger TEN(10);
387 vector<char>::const_reverse_iterator end = this->value.rend();
388 vector<char>::const_reverse_iterator ite = this->value.rbegin();
389 vector<int> quotients;
390 while(ite != end)
391 {
392 temp = temp * TEN + BigInteger((int)((*ite) - '0'));
393 int quotient = 0;
394 while(temp >= right)
395 {
396 temp = temp - right;
397 ++quotient;
398 }
399 quotients.push_back(quotient);
400 ++ite;
401 }
402
403 vector<char> result;
404 vector<int>::reverse_iterator i_end = quotients.rend();
405 for(vector<int>::reverse_iterator ite = quotients.rbegin(); ite != i_end; ++ite)
406 {
407 result.push_back((char)(*ite) + '0');
408 }
409
410 BigInteger integer(result, this->isMinus || right.isMinus);
411 integer.Trim();
412 return integer;
413 }
414
415 // delegate to -,/,* operations
416 BigInteger operator%(const BigInteger & right) const
417 {
418 return *this - (*this / right * right);
419 }
420
421 // delegate to * operations
422 BigInteger Pow(int n)
423 {
424 assert(n >= 0);
425 BigInteger result(1);
426 while(n != 0 && n--)
427 {
428 result = result * *this;
429 }
430 return result;
431 }
432
433 friend ostream & operator<<(ostream & os, const BigInteger & integer)
434 {
435 vector<char>::const_reverse_iterator ite = integer.value.rbegin();
436 vector<char>::const_reverse_iterator end = integer.value.rend();
437
438 if(integer.isMinus)
439 os << "-";
440
441 for(; ite != end; ++ite)
442 {
443 os << (*ite);
444 }
445 return os;
446 }
447
448 friend istream & operator>>(istream & is, BigInteger & integer)
449 {
450 string input;
451 is >> input;
452 integer = BigInteger(input);
453 return is;
454 }
455
456 size_t Length() const
457 {
458 return value.size();
459 }
460
461 int operator[](size_t index)
462 {
463 if(index > Length())
464 throw new exception("");
465 return value[index] - '0';
466 }
467
468 int operator[](size_t index) const
469 {
470 if(index > Length())
471 throw new exception("");
472 return value[index] - '0';
473 }
474
475 // parse to int value
476 int GetIntValue() const
477 {
478 int result = 0, index = 0;
479 vector<char>::const_iterator end = value.end();
480 for(vector<char>::const_iterator ite = value.begin(); ite != end; ++ite)
481 {
482 result += ((*ite) - '0') * (int)pow((double)10, index++);
483 }
484 return result;
485 }
486
487 // parse to string
488 string GetString() const
489 {
490 string result;
491 vector<char>::const_iterator end = value.end();
492 int index = 0;
493 for(vector<char>::const_iterator ite = value.begin(); ite != end; ++ite, ++index)
494 {
495 result += *ite;
496 }
497 return result;
498 }
499};
500
501#endif
502
503
posted on 2009-03-26 21:41
肖羽思 阅读(739)
评论(0) 编辑 收藏 引用 所属分类:
ZOJ