51nod基础题感触(1005大数加法)

这篇就作为算法学习这块的第一篇文章啦!之前一直想来写一下博客来着,但是自己太懒了,建模比赛后想多休息(玩)一会儿(很长时间),一直没写。最近总算是下定决定了!

“的确是要开始写一写最近自己做题的感受了!”(超认真的!)

直入正题!(由于才正式开始学习,理解有不足之处还请指正!)

首先,遇到这样的题,如果不限制语言的话,抱着能快则快的心态,我们就用强大的Python就行了。实现起来也是十分地的简单,在这里,我就直接上代码啦!(这里我用的是Python3.6)

     a=input()#输入,这时候的a实际上还是字符串

      b=input()

      print(int(a)+int(b))#字符串转整形,进行加法运算

这样来看,Python在处理大数方面真地很方便,如果条件允许,推荐用Python来解题。但是,凡是还是要“知其然,更知其所以然”呀!所以这里我就依着我个人看资料后的个人理解用C++为大家讲一下吧!

我们的任务就是完成这样一个式子的计算

那么,我们大数要怎么计算呢?

这里我们先从简单的情况出发——两个非负数相加。

对此,我分为这样几个步骤:

   1)正向数组存储 2)反向切割转化 3)逐位相加  4)反向输出

      1)正向数组存储

      为了方便讲解,我们以数12356611(A)、48661613(B)为例。(实际的int的范围可以去百度了解下,这里我们假设这时候整形就爆了!:P)

录入之后char数组的情况就是这样的,这里我们用str1承接A,str2承接B,A对应的位数为A_len,B对应的位数为B_len。

     2)反向切割转化

得到str1、str2后,我们再将他们反向录入足够长的int数组中

     3)逐位相加

我们需要由低位至高位逐项相加,并且,在计算的时候我们还需要设定一个变量CF来储存上次的进位信息,拿图中的例子来说:首先我们先让A[0]、B[0]相加,得到最开始的C[0],然后用语句CF = C[0]/10得到CF的进位值0,用语句C[0] =C[0]%10得到C[0]的值,然后,我们继续计算,让A[1]、B[1]与CF一同相加,我们得到了最开始的C[1],接着按照老办法,CF = C[1]/10得到新的CF,C[1] = C[1]%10……如此循环,直到计算到i = max(A_len,B_len) ,也就是说计算到“ 最大和数位数 + 1 ”的位。

另外,这里还要注明一下的是C[i] 是预先初始化为0的!承接str1、str2的整形数组A、B也是经过初始化为0才能接受str1、str2的。

     4)反向输出

在这里,我们只需要“正确”反向输出经过处理的C数组内的内容就行了!虽然这段话看起来简单,但是想“正确输出”,没接触过的小白写程序的时候还是要多注意下这个问题——C的最高位在哪里?看到这个问题,如果不加思考,很容易就会写成“这还不简单?开头不就是很多0吗?从第max(A_len,B_len) + 1位开始,遇0不输出”。好了,这下可能该丢的0、不该丢的0都丢了。正确的想法应该是在前者的基础上改成“开始遇0不输出,但一遇到非0就停下来,然后找到了最高位的位置,按情况输出”。如果想更快点,可以就在计算和的时候给最后的逐位计算来个CF的特判,直接找到最高位。

了解了两个非负数相加,我们再考虑更复杂的情况——两个整数相加。

两个整数相加,情况一共有三种:两非负数相加;一非负、一负相加;两负相加。再想一想,两负数相加实际上就是两负数的绝对值相加再加上负号,而一非负、一负相加实际上就是先判断符号,再计算两数相减的绝对值,所以计算的模式实际上就是两种:非负数相加模式(也就是之前说的简单情况),非负数相减模式(新增的哦!)。

接下来,继续分析大数非负数相减。这里我们的思路与非负数大数相加类似,但是还是有区别的!过程分为这样几步:

1)正向数组存储 2)反向切割转化 3)结果符号判断 4)逐位相减  5)反向输出

      在这里,为了有助于理解,我们用 1115545(A)、-1253564(B) 来进行讲解

      1)正向数组存储

我们用str1、str2分别存储A、B。

      2)反向切割转化

这里我们根据str1、str2中有无负号得到A、B的位数,它们分别为A_len,B_len。

      3)结果符号判断

对于符号的判断,我们可以根据下方的伪代码来进行判断

if(A_len!= B_len)
{
       if(A_len>B_len)
     {
        //A的长度大于B,A为正数,所以结果为正数,下接A-B大数减法
     }
}
 else
{
       int flag=0;
       int i=A_len-1;
       for(;i>0;i--)
      {
           if(A[i]>B[i])
         {
            flag=1;//A比B大
         }
     }
         if(i<0)
     {
        输出0;
        return 0;
  }
        if(flag)
     {
        //A-B>0,下接A-B大数减法
      }
      else
     {
       //A-B<0,下接B-A大数减法
      }
}

      4)逐位相减

这里,与小学数学减法计算类似,我们从低位开始向高位计算,同时用br存储借位信息,用于后续的计算。

万事俱备,我们从 i=A_len - 1 开始计算。开始的时候,用A[6] - B[6]得到初始的C[6],然后检测C[6]是否小于0,结果不是,然后确定初始C[6]就是我们要求的C[6],继续计算C[5],同样的方法,我们得到C[5]为-1,我们发现C[5]是小于0的,所以需要借位,让C[4]减1,同时再让初始C[5]+10,得到的结果为9,接着继续计算,直到算出C[0]。同时,我们在计算的时候用一个整型变量rec记录不为零的位的下标,直到记录到最后一个非零位下标。

经过计算,我们得到如下结果。

5)反向输出

根据“结果符号判断”得出的结论进行符号输出,从下标为rec的C的数组元素开始逐个输出。

附C++代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main ()
{
    int a[10005]={0},b[10005]={0},c[10005]={0},la,lb,lc,x=0,nega=0,add=0,flag=0,bigger=1;
  //数组a,b代表被加数  c代表和数
    char a1[10005],b1[10005];
 //方便输入以及进行倒序用
    gets(a1);
    gets(b1);
    if(a1[0]==‘-‘||b1[0]==‘-‘)//至少有一个为负
    {
       if(a1[0]==‘-‘&&b1[0]==‘-‘)//均为负
       {
             nega=1;  //均为负数标志
             add=1;   //类同两非负数相加
             la=strlen(a1)-1;
             lb=strlen(b1)-1;
       }
       else //一个为负
       {
             flag=1;
             add=0; //类同两非负数相减
       }
    }
    else if(a1[0]==‘0‘&&b1[0]==‘0‘) //均为0
            cout<<0;
    else  //均为非负
    {
          la=strlen(a1);
                 lb=strlen(b1);
          for(int i=0;i<=la-1;i++)     //进行倒序a
          {
            a[la-i]=a1[i]-‘0‘;
          }
          for (int j=0;j<=lb-1;j++)   //进行倒序b
          {
            b[lb-j]=b1[j]-‘0‘;
          }
          lc=1;
          while(lc<=la||lc<=lb)   //进行加法进位
          {
            c[lc]=a[lc]+b[lc]+x;
            x=c[lc]/10;
            c[lc]%=10;
            lc++;
          }
            c[lc]=x;
          while(c[lc]==0)  //确定最高位
          {
            lc--;
          }
          for(int k=lc;k>=1;k--)   //注意存放在数组中的数是倒序的
          {
            cout<<c[k];
          }
            return 0;
       }
        if(nega==1&&add==1)//均为负数
     {
          for(int i=0;i<=la-1;i++)     //进行倒序a
        {
            a[la-i]=a1[i+1]-‘0‘;
            //cout<<la-i<<" "<<a[la-i]<<"||";
        }
        //cout<<endl;
        for (int j=0;j<=lb-1;j++)   //进行倒序b
        {
            b[lb-j]=b1[j+1]-‘0‘;
            //cout<<lb-j<<" "<<b[lb-j]<<"||";
        }
        //cout<<endl;
        lc=1;
        while(lc<=la||lc<=lb)   //进行加法进位
        {
            c[lc]=a[lc]+b[lc]+x;
            x=c[lc]/10;
            c[lc]%=10;
            //cout<<lc<<" "<<c[lc]<<"||"<<endl;
            lc++;
        }
        c[lc]=x;
        while(c[lc]==0)  //注意最高位为0要舍弃
        {
            lc--;
        }
        cout<<‘-‘;
        for(int k=lc;k>=1;k--)   //注意存放在数组中的数是倒序的
        {
            cout<<c[k];
        }
     }
     if(flag==1&&add==0)
     {
         if(a1[0]==‘-‘)  //a为负,b为正
         {

               int rec=0;
             la=strlen(a1)-1;
             lb=strlen(b1);
             for(int i=0;i<=la-1;i++)     //进行倒序A
            {
                a[la-i]=a1[i+1]-‘0‘;
            //    cout<<la-i<<" "<<a[la-i]<<"||";
            }
            //cout<<endl;
            for (int j=0;j<=lb-1;j++)   //进行倒序B
            {
                b[lb-j]=b1[j]-‘0‘;
            //    cout<<lb-j<<" "<<b[lb-j]<<"||";
            }
            //cout<<endl;

             if(la>lb)
             {
                  bigger=0;        //|a|大
             }
             else if(la<lb)
             {
                   bigger=1;    //|b|大
             }
             else if(la==lb)
             {
                 for (int q=la;q>=1;q--)
                 {
                     //cout<<a[q]<<" "<<b[q]<<endl;
                     if(a[q]>b[q])
                     {
                         bigger=0;
                         break;
                     }
                    else if(a[q]<b[q])
                     {
                         bigger=1;
                         break;
                     }
                 }
             }

            if(bigger==0)   //a更大
            {
                for(int q=1;q<=la;q++)
                {
                    a[q]-=b[q];                    if(a[q]<0)
                    {
                        a[q]+=10;
                        a[q+1]--;
                     }
                    if(a[q]!=0)
                    rec=q;
                }
                if(rec!=0)
                {
                    cout<<"-";
                    for(int q=rec;q>=1;q--)
                    {
                        cout<<a[q];
                    }
                }
                else
                {
                    cout<<0;
                }
            }
            else if(bigger==1)  //b更大
            {
                for(int q=1;q<=lb;q++)
                {
                    b[q]-=a[q];

                    if(b[q]<0)
                    {
                        b[q]+=10;
                        b[q+1]--;
                     }
                     if(b[q]!=0)
                    rec=q;
                }
                if(rec!=0)
                {
                    for(int q=rec;q>=1;q--)
                    {
                        cout<<b[q];
                    }
                }
                else
                {
                    cout<<0;
                }
            }
        }
         else if(b1[0]==‘-‘)    //a为正,b为负
        {
            int rec=0;
             la=strlen(a1);
             lb=strlen(b1)-1;
             for(int i=0;i<=la-1;i++)     //进行倒序a
            {
                a[la-i]=a1[i]-‘0‘;
                //cout<<la-i<<" "<<a[la-i]<<"||";
            }
            //cout<<endl;
            for (int j=0;j<=lb-1;j++)   //进行倒序b
            {
                b[lb-j]=b1[j+1]-‘0‘;
                //cout<<lb-j<<" "<<b[lb-j]<<"||";
            }
            //cout<<endl;

             if(la>lb)
             {
                  bigger=0;        //|a|大
             }
             else if(la<lb)
             {
                   bigger=1;    //|b|大
             }
             else
             {
                 for (int q=la;q>=1;q--)
                 {
                     //cout<<a[q]<<" "<<b[q]<<endl;
                     if(a[q]>b[q])
                     {
                         bigger=0;
                         break;
                     }
                     else if(a[q]<b[q])
                     {
                         bigger=1;
                         break;
                     }
                 }
             }
            if(bigger==0)   //a更大
            {

                for(int q=1;q<=la;q++)
                {
                    a[q]-=b[q];

                    if(a[q]<0)
                    {
                        a[q]+=10;
                        a[q+1]--;
                     }
                    if(a[q]!=0)
                    rec=q;
                }
                if(rec!=0)
                {

                    for(int q=rec;q>=1;q--)
                    {
                        cout<<a[q];
                    }
                }
                else
                {
                    cout<<0;
                }
            }
            else if(bigger==1)  //b更大
            {

                for(int q=1;q<=lb;q++)
                {
                    b[q]-=a[q];

                    if(b[q]<0)
                    {
                        b[q]+=10;
                        b[q+1]--;
                     }
                    if(b[q]!=0)
                    rec=q;
                }
                if(rec!=0)
                {
                    cout<<"-";
                    for(int q=rec;q>=1;q--)
                    {
                        cout<<b[q];
                    }
                }
                else
                {
                    cout<<0;
                }
            }

        }
     }

        return 0;
}                        

原文地址:https://www.cnblogs.com/memocean/p/11438334.html

时间: 2024-10-12 22:17:22

51nod基础题感触(1005大数加法)的相关文章

51 Nod 1005 大数加法【Java大数乱搞,python大数乱搞】

1005 大数加法 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出2个大整数A,B,计算A+B的结果. Input 第1行:大数A 第2行:大数B (A,B的长度 <= 10000 需注意:A B有可能为负数) Output 输出A + B Input示例 68932147586 468711654886 Output示例 537643802472 题目链接:http://www.51nod.com/onlineJudge/questionCode.html#

1005 大数加法

1005 大数加法 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 给出2个大整数A,B,计算A+B的结果. Input 第1行:大数A 第2行:大数B (A,B的长度 <= 10000 需注意:A B有可能为负数) Output 输出A + B Input示例 68932147586 468711654886 Output示例 537643802472 c++代码 1 #include <iostream> 2 #include <cstring&g

1058 N的阶乘的长度(51NOD基础题)

1058 N的阶乘的长度(51NOD基础题) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 输入N求N的阶乘的10进制表示的长度.例如6! = 720,长度为3. Input 输入N(1 <= N <= 10^6) Output 输出N的阶乘的长度 Input示例 6 Output示例 3 /* n! 的长度 len = (int)log10(n!) + 1 ; -->> len = log10(1) + log10(2) + .... + log1

1057 N的阶乘(51NOD基础题)

1057 N的阶乘(51NOD基础题) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 输入N求N的阶乘的准确值. Input 输入N(1 <= N <= 10000) Output 输出N的阶乘 Input示例 5 Output示例 120 思路:由于最终结果比较大正常的 LL 肯定是不行的 , 所以仿照 10 进制数 构造出 10000 进制数 , 对万进制数的操作仿照十进制 #include <cstdio> #include <cstri

1012 最小公倍数LCM(51NOD基础题)

1012 最小公倍数LCM(51NOD基础题) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 输入2个正整数A,B,求A与B的最小公倍数. Input 2个数A,B,中间用空格隔开.(1<= A,B <= 10^9) Output 输出A与B的最小公倍数. Input示例 30 105 Output示例 210 #include <cstdio> #define LL long long LL n , m ; LL result ; // 递归实现辗

1011 最大公约数GCD(51NOD基础题)

1011 最大公约数GCD(51NOD基础题) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 输入2个正整数A,B,求A与B的最大公约数. Input 2个数A,B,中间用空格隔开.(1<= A,B <= 10^9) Output 输出A与B的最大公约数. Input示例 30 105 Output示例 15 /* <1> 循环实现 辗转相除法 <2> 递归实现 辗转相除法 */ #include <cstdio> #defi

51nod 1005 大数加法

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 Input 第1行:大数A 第2行:大数B (A,B的长度 <= 10000 需注意:A B有可能为负数) Output 输出A + B Input示例 68932147586 468711654886 Output示例 537643802472 Java在处理大数据方面很具有优势~~~~~~~~~~~~~~~~~~~ import java.math.BigInteger; import java.util.Scan

1008 N的阶乘 mod P(51NOD基础题)

1008 N的阶乘 mod P(51NOD) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 输入N和P(P为质数),求N! Mod P = ? (Mod 就是求模 %) 例如:n = 10, P = 11,10! = 3628800 3628800 % 11 = 10 Input 两个数N,P,中间用空格隔开.(N < 10000, P < 10^9) Output 输出N! mod P的结果. Input示例 10 11 Output示例 10 #includ

【51Nod】1005 大数加法

给出2个大整数A,B,计算A+B的结果. Input 第1行:大数A 第2行:大数B (A,B的长度 <= 10000 需注意:A B有可能为负数) Output 输出A + B Input示例 68932147586 468711654886 Output示例 537643802472 ==================================================================================================== 问题解法