poj中的大数乘法!

来源:互联网 发布:二号首长 知乎 编辑:程序博客网 时间:2024/05/24 06:50

题目:

Bull Math

Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 12786 Accepted: 6584

Description

Bulls are so much better at math than the cows. They can multiply huge integers together and get perfectly precise answers ... or so they say. Farmer John wonders if their answers are correct. Help him check the bulls' answers. Read in two positive integers (no more than 40 digits each) and compute their product. Output it as a normal number (with no extra leading zeros).

FJ asks that you do this yourself; don't use a special library function for the multiplication.

Input

* Lines 1..2: Each line contains a single decimal number.

Output

* Line 1: The exact product of the two input lines

Sample Input

111111111111111111111111

Sample Output

12345679011110987654321

Source

USACO 2004 November

[Submit]   [Go Back]   [Status]   [Discuss]

Home Page  Go Back  To top

 

中文翻译:

                           公牛在数学方面与奶牛相比要好很多,他们可以把巨大的数相乘得到完美精确地答案农场主约翰就请你编程验证答案是否正确,给出两个不超过40位的正整数,计算出乘积(无前导0)

每个数据一行,输出一行。

题目大意:

计算两个不超过40位的大数相乘

 

解题思路:

           因为大数是说的:一、数值大 二、精确度高,

       本题因为是整数的相乘,所以就不涉及精确度的问题,只需考虑数值的大小。

存储:

       要计算两个数相乘,需要先输入,然后存储下来,再进行计算,由于数值较大,一般的整形变量难以正确存储,所以可以借助数组进行数据的存储。

 

运算:

       本题的数据在40位以内,不算太大,可以直接模拟乘法运算,(对于较大的数需要采用傅里叶转换),最后再进行进位处理。

 

输出:

        输出时要去除前导0;对此,可以采用将数倒置放入数组中,以个位对齐,得运算结果,然后逆序输出,(过滤掉前导0)。

 

关键点:

1、先像大数加法那样,进行存储数据

2、乘法的模拟运算

3、去除前导0

 

难点:

乘法模拟:

在进行运算时相乘得到的结果应该存储到对应的位置

 for(i=0;i<l1;i++){
  for(j=0;j<l2;j++){
   a[i+j]+=b1[i]*b2[j];
  }

即:b1[i]*b2[j]应该存储在a数组对应的i+j+1位上,也即a[i+j] 、(a[0]为第一个元素)

进位处理 : 

 

之前的代码

 for(i=0;i<M*2;i++){
 s=a[i];
  for(j=i;;j++){   //此处是计算的核心部分,尤其是将a[i]分解加到高位上时
   if(j==i)
    a[j]=a[j]%10; //本位就是自身对10的余数。而其他位的要加上来自后面的进位,,也即将自身的个位留下,将高位逐个加到前面去
   else
   a[j]=a[j]+s%10;
   s/=10;
   if(s==0)
   break;
  }

 

后来发现根本不需要这么麻烦,因为在这一步只需得到这一为的值即可,多出来的都加到高位,无需精确加到了哪一位,因为高位的值还不真正确定,只需后来对其做同样处理,确定即可:

优化如下:

 if(a[i]>=10)
  {
   a[i+1]+=a[i]/10;  //注意:此处要加在前一位上,而不是直接赋值 
   a[i]%=10;
  }

 

 

源代码:

# include<stdio.h>
# include<string.h>
# define M 50
char c1[M+50],c2[M+50];
int b1[M+50],b2[M+50];
int a[2*M+50];
int main(){
    int i,j,k,l;
    int l1,l2;
    int t,s;
 while(~scanf("%s%s",c1,c2)){
    memset(b1,0,sizeof(b1));
    memset(b2,0,sizeof(b2));
    memset(a,0,sizeof(a));
   
    l1=strlen(c1);
    l2=strlen(c2);
    for(i=l1-1,j=0;i>=0;i--){
  b1[j++]=c1[i]-'0';
 }
    for(i=l2-1,j=0;i>=0;i--){
  b2[j++]=c2[i]-'0';
 }
 for(i=0;i<l1;i++){
  for(j=0;j<l2;j++){
   a[i+j]+=b1[i]*b2[j];
  }
 }
 
  for(i=0;i<M*2;i++){
 /* s=a[i];
  for(j=i;;j++){   //此处是计算的核心部分,尤其是将a[i]分解加到高位上时
   if(j==i)
    a[j]=a[j]%10; //本位就是自身对10的余数。而其他位的要加上来自后面的进位,,也即将自身的个位留下,将高位逐个加到前面去
   else
   a[j]=a[j]+s%10;
   s/=10;
   if(s==0)
   break;
  }
  */
  
  if(a[i]>=10)
  {
   a[i+1]+=a[i]/10;  //注意:此处要加在前一位上 
   a[i]%=10;
  }
  
  
 }
 for(i=M*2+10;i>=0&&a[i]==0;i--);
 if(i>=0)
 {
  for(;i>=0;i--)
  printf("%d",a[i]);
  printf("\n");
 }
 else
 printf("0\n");
 }
 return 0;
}

解题体会:

做这样的题的时候,模拟运算也是很重要的!

 

 

解题人:李富昌


 

0 0