• [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<<'
    ';
    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<<'
    ';
    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 }
  • 相关阅读:
    java设计模式之适配器模式
    在Eclipse中建立Maven Web项目
    java设计模式之原型模式
    java设计模式之建造者模式
    java设计模式之工厂模式
    java设计模式之单例模式
    C# 前端多次上传文件
    C# async 和 await
    .NET 4.0 任务(Task)
    C# 5.0
  • 原文地址:https://www.cnblogs.com/night-ride-depart/p/4419105.html
Copyright © 2020-2023  润新知