[acm 1001] c++ 大数加法 乘法 幂

北大的ACM 1001

poj.org/problem?id=1001

 

代码纯手动编写 - -

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 
  6 class BigNumber
  7 {
  8     struct BigNumberNode
  9     {
 10         BigNumberNode():n(0), prev(NULL), next(NULL){}
 11         BigNumberNode(int N):n(N), prev(NULL), next(NULL){}
 12 
 13         int n;
 14         BigNumberNode *prev, *next;
 15     };
 16 
 17     BigNumberNode *head, *tail;
 18     int dot_before; // 小数点之前的数量
 19     int dot_later;  // 小数点之后的数量
 20 
 21     void InsertNodeAtBegin(int n)
 22     {
 23         BigNumberNode *new_node = new BigNumberNode(n);
 24         if(head != NULL)
 25         {
 26             head->prev = new_node;
 27             new_node->prev = NULL;
 28             new_node->next = head;
 29             head = new_node;
 30         }
 31         else
 32         {
 33             head = new_node;
 34             tail = new_node;
 35             new_node->prev = NULL;
 36             new_node->next = NULL;
 37         }
 38     }
 39 
 40     void InsetNodeAtEnd(int n)
 41     {
 42         BigNumberNode *new_node = new BigNumberNode(n);
 43         if(head != NULL)
 44         {
 45             new_node->prev = tail;
 46             new_node->next = NULL;
 47             tail->next = new_node;
 48             tail = new_node;
 49         }
 50         else
 51         {
 52             head = new_node;
 53             tail = new_node;
 54             new_node->prev = NULL;
 55             new_node->next = NULL;
 56         }
 57     }
 58 
 59     void DeleteBegin()
 60     {
 61         if(head != NULL)
 62         {
 63             if (head->next != NULL)
 64             {        
 65                 BigNumberNode* temp = head->next;
 66                 delete head;
 67                 head = temp;
 68                 temp->prev = NULL;
 69 
 70                 if (dot_before != 0)
 71                 {
 72                     dot_before--;
 73                 }
 74                 else
 75                 {
 76                     dot_later--;
 77                 }
 78             }
 79             else
 80             {
 81                 Free();
 82             }
 83         }
 84     }
 85 
 86     void DeleteEnd()
 87     {
 88         if(tail != NULL)
 89         {
 90             if (tail->prev != NULL)
 91             {        
 92                 BigNumberNode* temp = tail->prev;
 93                 delete tail;
 94                 tail = temp;
 95                 temp->next = NULL;
 96 
 97                 if (dot_later != 0)
 98                 {
 99                     dot_later--;
100                 }
101                 else
102                 {
103                     dot_before--;
104                 }
105             }
106             else
107             {
108                 Free();
109             }
110         }
111     }
112 
113     // 去除前/后导 0
114     // 去除前/后导 0
115     void ClearZeros()
116     {
117         // 后导 0
118         BigNumberNode *p;
119 
120         int max_limit = dot_later;
121         for(int i = 0; i < max_limit; i++)
122         {
123             p = tail;
124 
125             if(p->n == 0)
126             {
127                 DeleteEnd();
128             }
129             else
130             {
131                 break;
132             }
133         }
134 
135         // 前导 0
136         max_limit = dot_before;
137         for(int i = 0; i < max_limit; i++)
138         {
139             p = head;
140 
141             if(p->n == 0)
142             {
143                 DeleteBegin();
144             }
145             else
146             {
147                 break;
148             }
149         }
150     }
151 
152     BigNumber Mul(const BigNumber &Scale)
153     {
154         const BigNumber &a = *this, &b = Scale;
155         BigNumber sum_big_number;
156 
157         int sum = 0;
158         int reserve = 0;
159         int tag = 0;
160 
161         BigNumberNode *pa = a.tail, *pb = b.tail;
162 
163         //    xxxxxx a
164         //       xxx b
165         // --------- Mul
166         //    xxxxxx
167         //   xxxxxx
168         //  xxxxxx
169         // --------- Add
170         // xxxxxxxxx
171 
172         while(pb)
173         {
174             BigNumber temp_big_number;
175             pa = a.tail;
176             while(pa)
177             {
178                 sum = pa->n * pb->n + reserve;
179                 reserve = sum / 10;
180                 temp_big_number.InsertNodeAtBegin(sum - reserve * 10);
181                 temp_big_number.dot_before++;
182                 pa = pa->prev;
183             }
184 
185             if (reserve)
186             {
187                 temp_big_number.InsertNodeAtBegin(reserve);
188                 temp_big_number.dot_before++;
189                 reserve = 0;
190             }
191 
192             for (int i = 0; i < tag; i++)
193             {
194                 temp_big_number.InsetNodeAtEnd(0);
195                 temp_big_number.dot_before++;
196             }
197 
198             sum_big_number += temp_big_number;
199 
200             tag++;
201             pb = pb->prev;
202         }
203 
204         sum_big_number.dot_later = a.dot_later + b.dot_later;
205 
206         if (sum_big_number.dot_before > sum_big_number.dot_later)
207         {
208             sum_big_number.dot_before -= sum_big_number.dot_later;
209         }
210         else
211         {
212             int temp = sum_big_number.dot_later - sum_big_number.dot_before;
213             sum_big_number.dot_before = 0;
214             for (int i = 0; i < temp; i++)
215             {
216                 sum_big_number.InsertNodeAtBegin(0);
217             }
218         }
219 
220         sum_big_number.ClearZeros();
221 
222         return sum_big_number;
223     }
224 
225 public:
226 
227     ~BigNumber()
228     {
229         Free();
230     }
231 
232     BigNumber(): head(NULL), tail(NULL), dot_before(0), dot_later(0)
233     {
234     }
235 
236     BigNumber(const char *Str): head(NULL), tail(NULL), dot_before(0), dot_later(0)
237     {
238         Free();
239         AdaptFormString(Str);
240     }
241 
242     BigNumber(const BigNumber& Source): head(NULL), tail(NULL), dot_before(0), dot_later(0)
243     {
244         *this = Source;
245     }
246 
247     const BigNumber& operator=(const BigNumber& Source)
248     {
249         if (this != &Source)
250         {
251             this->Free();
252 
253             BigNumberNode *p = Source.head;
254             while(p)
255             {
256                 this->InsetNodeAtEnd(p->n);
257                 p = p->next;
258             }
259 
260             this->dot_before = Source.dot_before;
261             this->dot_later = Source.dot_later;
262         }
263 
264         return *this;
265     }
266 
267     BigNumber operator+(const BigNumber Addend)
268     {
269         const BigNumber &a = *this, &b = Addend;
270         BigNumber new_number;
271 
272         BigNumberNode *pa, *pb;
273         int sum, remain, odd;
274         int reserve = 0;
275         bool is_dot_before_longer_is_a; // 帮助标记小数点之前的部分
276         bool is_dot_later_longer_is_a;
277 
278         // 小数点之后
279         if(a.dot_later > b.dot_later)
280         {
281             pa = a.tail;
282             pb = b.tail;
283             remain = b.dot_later;
284             odd = a.dot_later - b.dot_later;
285             is_dot_later_longer_is_a = true;
286         }
287         else
288         {
289             pa = b.tail;
290             pb = a.tail;
291             remain = a.dot_later;
292             odd = b.dot_later - a.dot_later;
293             is_dot_later_longer_is_a = false;
294         }
295 
296         for (int i = 0; i < odd; i++)
297         {
298             new_number.InsertNodeAtBegin(pa->n);
299             new_number.dot_later++;
300             pa = pa->prev;
301         }
302 
303         for (int i = 0; i < remain; i++)
304         {
305             sum = pa->n + pb->n + reserve;
306             reserve = sum / 10;
307             new_number.InsertNodeAtBegin(sum - reserve * 10);
308             new_number.dot_later++;
309             pa = pa->prev;
310             pb = pb->prev;
311         }
312 
313         // 小数点之前
314         if(a.dot_before > b.dot_before)
315         {
316             remain = b.dot_before;
317             odd = a.dot_before - b.dot_before;
318             is_dot_before_longer_is_a = true;
319         }
320         else
321         {
322             remain = a.dot_before;
323             odd = b.dot_before - a.dot_before;
324             is_dot_before_longer_is_a = false;
325         }
326 
327         BigNumberNode *temp; // 用于交换 pa pb
328         if (is_dot_before_longer_is_a && is_dot_later_longer_is_a 
329             || !is_dot_before_longer_is_a && !is_dot_later_longer_is_a)
330         {
331             // 不用交换
332         }
333         else
334         {
335             temp = pa;
336             pa = pb;
337             pb = temp;
338         }
339 
340 
341         for (int i = 0; i < remain; i++)
342         {
343             sum = pa->n + pb->n + reserve;
344             reserve = sum / 10;
345             new_number.InsertNodeAtBegin(sum - reserve * 10);
346             new_number.dot_before++;
347             pa = pa->prev;
348             pb = pb->prev;
349         }
350 
351         for (int i = 0; i < odd; i++)
352         {
353             sum = pa->n + reserve;
354             reserve = sum / 10;
355             new_number.InsertNodeAtBegin(sum - reserve * 10);
356             new_number.dot_before++;
357             pa = pa->prev;
358         }
359 
360         // 检测是否最后还有一位
361         if (reserve)
362         {
363             new_number.InsertNodeAtBegin(reserve);
364             new_number.dot_before++;
365             reserve = 0;
366         }
367 
368         new_number.ClearZeros();
369 
370         return new_number;
371     }
372 
373     BigNumber operator*(const BigNumber& Scale)
374     {
375         return Mul(Scale);
376     }
377 
378     BigNumber& operator+=(const BigNumber Addend)
379     {
380         BigNumber &a = *this;
381         const BigNumber &b = Addend;
382 
383         BigNumberNode *pa = a.tail, *pb = b.tail;
384         int sum = 0, remain = 0, odd = 0;
385         int reserve = 0;
386 
387         // 小数点之后
388         if(a.dot_later > b.dot_later)
389         {
390             remain = b.dot_later;
391             odd = a.dot_later - b.dot_later;
392 
393             for (int i = 0; i < odd; i++)
394             {
395                 pa = pa->prev;
396             }
397         }
398         else
399         {
400             remain = a.dot_later;
401             odd = b.dot_later - a.dot_later;
402 
403             char *odd_n = new char[odd];
404             for (int i = 1; i <= odd; i++)
405             {
406                 odd_n[odd - i] = pb->n;
407                 pb = pb->prev;                
408             }
409 
410             for (int i = 0; i < odd; i++)
411             {
412                 a.InsetNodeAtEnd(odd_n[i]);
413                 a.dot_later++;
414             }
415             delete odd_n;
416         }
417 
418         for (int i = 0; i < remain; i++)
419         {
420             sum = pa->n + pb->n + reserve;
421             reserve = sum / 10;
422             pa->n = sum - reserve * 10;
423 
424             pa = pa->prev;
425             pb = pb->prev;
426         }
427 
428         // 小数点之前
429         if(a.dot_before > b.dot_before)
430         {
431             remain = b.dot_before;
432             odd = a.dot_before - b.dot_before;
433 
434             for (int i = 0; i < remain; i++)
435             {
436                 sum = pa->n + pb->n + reserve;
437                 reserve = sum / 10;
438                 pa->n = sum - reserve * 10;
439 
440                 pa = pa->prev;
441                 pb = pb->prev;
442             }
443 
444             for (int i = 0; i < odd; i++)
445             {
446                 sum = pa->n + reserve;
447                 reserve = sum / 10;
448                 pa->n = sum - reserve * 10;
449 
450                 pa = pa->prev;
451             }
452         }
453         else
454         {
455             remain = a.dot_before;
456             odd = b.dot_before - a.dot_before;
457 
458             for (int i = 0; i < remain; i++)
459             {
460                 sum = pa->n + pb->n + reserve;
461                 reserve = sum / 10;
462                 pa->n = sum - reserve * 10;
463 
464                 pa = pa->prev;
465                 pb = pb->prev;
466             }
467 
468             for (int i = 0; i < odd; i++)
469             {
470                 sum = pb->n + reserve;
471                 reserve = sum / 10;
472                 a.InsertNodeAtBegin(sum - reserve * 10);
473                 a.dot_before++;
474                 pb = pb->prev;
475             }
476 
477         }
478 
479         // 检测是否最后还有一位
480         if (reserve)
481         {
482             a.InsertNodeAtBegin(reserve);
483             a.dot_before++;
484         }
485 
486         a.ClearZeros();
487 
488         return *this;
489     }
490 
491     void _Print()
492     {
493         if(dot_before == 0 && dot_later == 0)
494         {
495             putchar('0');
496         }
497         else if (dot_later == 0)
498         {
499             BigNumberNode *p = head;
500 
501             while(p)
502             {
503                 putchar(p->n + '0');
504                 p = p->next;
505             }
506         }
507         else
508         {
509             BigNumberNode *p = head;
510 
511             for(int i = 0; i < dot_before; i++)
512             {
513                 putchar(p->n + '0');
514                 p = p->next;
515             }
516 
517             putchar('.');
518 
519             while(p)
520             {
521                 putchar(p->n + '0');
522                 p = p->next;
523             }
524         }
525     }
526 
527     void PrintString()
528     {
529         if(dot_before == 0 && dot_later == 0)
530         {
531             putchar('0');
532         }
533         else if (dot_later == 0)
534         {
535             char *temp = new char[dot_before + dot_later + 2], *ptemp = temp;
536             BigNumberNode *p = head;
537 
538             while(p)
539             {
540                 *ptemp = p->n + '0';
541                 ptemp++;
542                 p = p->next;
543             }
544             *ptemp = 0;
545 
546             std::cout<<temp<<'\n';
547             delete[] temp;
548         }
549         else
550         {
551             char *temp = new char[dot_before + dot_later + 2], *ptemp = temp;
552             BigNumberNode *p = head;
553 
554             for(int i = 0; i < dot_before; i++)
555             {
556                 *ptemp = p->n + '0';
557                 ptemp++;
558                 p = p->next;
559             }
560 
561             *ptemp = '.';
562             ptemp++;
563 
564             while(p)
565             {
566                 *ptemp = p->n + '0';
567                 ptemp++;
568                 p = p->next;
569             }
570             *ptemp = 0;
571 
572             std::cout<<temp<<'\n';
573             delete[] temp;
574         }
575     }
576 
577     void Free()
578     {
579         BigNumberNode *p = head, *temp;
580 
581         while(p)
582         {
583             temp = p;
584             p = p->next;
585             delete temp;
586         }
587 
588         head = NULL;
589         tail = NULL;
590         dot_before = 0;
591         dot_later = 0;
592     }
593 
594     // 从字符串建立数据,未加入错误检测
595     void AdaptFormString(const char *Str)
596     {
597         Free();
598 
599         const char *pc = Str;
600 
601         // 小数点之前
602         while(*pc)
603         {
604             if(*pc != '.') // 0 ~ 9
605             {
606                 InsetNodeAtEnd(*pc - '0');
607                 dot_before++;
608                 pc++;
609             }
610             else // 小数点之后
611             {
612                 pc++;
613                 while(*pc)
614                 {
615                     InsetNodeAtEnd(*pc - '0');
616                     dot_later++;
617                     pc++;
618                 }
619                 break;
620             }
621         }
622 
623         ClearZeros();
624     }
625 
626 };
627 
628 // 自顶向下的动态规划
629 BigNumber* BigNumberPowUP(BigNumber* result[], int pow)
630 {
631     if( result[pow] )
632     {
633         return result[pow];
634     }
635     else
636     {
637         int left = pow / 2;
638         int right = pow - left;
639 
640         result[left] = BigNumberPowUP(result, left);
641         result[right] = BigNumberPowUP(result, right);
642 
643         result[pow] = new BigNumber((*result[left]) * (*result[right]));
644 
645         return result[pow];
646     }
647 }
648 
649 BigNumber BigNumberPow(const BigNumber& R, int pow)
650 {
651     BigNumber *result[26] = {0};
652 
653     result[1] = new BigNumber(R);
654 
655     BigNumberPowUP(result, pow);
656 
657     BigNumber Result = *result[pow];
658 
659     for (int i = 0; i <= pow; i++)
660     {
661         delete result[i];
662     }
663 
664     return Result;
665 }
666 
667 int main(void)
668 {
669     char Rstr[10];
670     int n;
671 
672     while(scanf("%s%d", Rstr, &n) != EOF)
673     {
674         BigNumber result = BigNumberPow(Rstr, n);
675         result.PrintString();
676     }
677 
678     return 0;
679 }

 

转载于:https://www.cnblogs.com/night-ride-depart/p/4419105.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值