Problem Description

I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B.

Input

The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line consists of two positive integers, A and B. Notice that the integers are very large, that means you should not process them by using 32-bit integer. You may assume the length of each integer will not exceed 1000.

Output

For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line is the an equation "A + B = Sum", Sum means the result of A + B. Note there are some spaces int the equation. Output a blank line between two test cases.

Sample Input

2
1 2
112233445566778899 998877665544332211

Sample Output

Case 1:
1 + 2 = 3

Case 2:
112233445566778899 + 998877665544332211 = 1111111111111111110

分析

说这是个very simple problem,其实是在坑你的~用计算A+B的普通方法是不行的,必须要高精度算法。

高精度算法就不细说了,大致就是模拟手算。先将个位相加,然后将十位相加,然后百位……当然如果有进位也要算上。要存储A、B两个大数,显而易见,需要使用数组。数组的每个元素都对应一个数位。

因为A、B最大长度是1000,所以用两个长度为1000的int数组(因为每个元素都是0~9,所以其实char就够了,甚至还可以用一个元素存N位):

int a[], b[];

A、B最大值是999...999(1000个9),因此A+B的最大值是1999...998(999个9),是1001位数。如果用数组c来存储结果,则c长度最大为1001:

int c[];

数组a、b、c的最后一个元素对应个位,倒数第二个元素对应十位,倒数第三个对应百位……设A、B长度为la、lb,记C=A+B,则C的长度lc最大为max{la, lb} + 1。因此需要从个位一直计算到10^(max{la, lb} + 1)位。最后需要考虑进位。代码:

void add(const int a[], int la, const int b[], int lb, int c[])
{
int lc = ((la > lb) ? la : lb) + ;
int g = ; // 是否进位
for (int i = ; i >= - lc; i--)
{
c[i + ] = a[i] + b[i] + g; // 因为c的大小为1001,a和b为1000,所以需要加上1001-1000=1,这样才是从c的末尾开始计算
g = c[i + ] / ; // 记录进位
c[i + ] %= ; // 将一个位限定在10以内
}
}

读入的时候就很简单了,如果是C用scanf()加%s,C++直接用cin。C代码:

char sa[], sb[];
scanf("%s%s", sa, sb);

A、B长度就用strlen()求出。

输出A和B时,直接将相应字符串输出就好了。至于C呢,可以从c[0]开始一直往后找到第一个非0位然后开始输出,或者记录下C的长度。

Final Code

Final code #1

#include <stdio.h>
#include <string.h> #define LEN 1000
#define LENC 1001 void convert(const char s[], int len, int a[]);
void add(const int a[], int la, const int b[], int lb, int c[]);
void print(const int c[]); int main()
{
int t;
char sa[LEN + ], sb[LEN + ];
int la, lb;
int a[LEN], b[LEN], c[LENC]; scanf("%d", &t); for (int i = ; i < t; i++)
{
for (int j = ; j < LEN + ; j++)
{
sa[j] = '\0';
sb[j] = '\0';
}
for (int j = ; j < LEN; j++)
{
a[j] = ;
b[j] = ;
}
for (int j = ; j < LENC; j++)
c[j] = ;
scanf("%s%s", sa, sb);
la = strlen(sa);
lb = strlen(sb);
printf("Case %d:\n%s + %s = ", i + , sa, sb);
convert(sa, la, a);
convert(sb, lb, b);
add(a, la, b, lb, c);
print(c);
printf("\n");
if (i < t - )
printf("\n");
} return ;
} void convert(const char s[], int len, int a[])
{
for (int i = ; i < len; i++)
a[LEN - len + i] = s[i] - '';
} void add(const int a[], int la, const int b[], int lb, int c[])
{
int lc = ((la > lb) ? la : lb) + ;
int g = ;
for (int i = LEN - ; i >= LEN - lc; i--)
{
c[i + LENC - LEN] = a[i] + b[i] + g;
g = c[i + LENC - LEN] / ;
c[i + LENC - LEN] %= ;
}
} void print(const int c[])
{
int s;
for (int i = ; i < LENC; i++)
if (c[i] != )
{
s = i;
break;
}
for (int i = s; i < LENC; i++)
printf("%d", c[i]);
}

因为提交时是C语言,所以常量是用#define定义的(const会有编译错误)。而且为了可读性以及逻辑上的清晰,我不惜将运行效率降低了。例如下面代码:

for (int j = ; j < LEN + ; j++)
{
sa[j] = '\0';
sb[j] = '\0';
}
for (int j = ; j < LEN; j++)
{
a[j] = ;
b[j] = ;
}
for (int j = ; j < LENC; j++)
c[j] = ;

本来可以连起来写成:

for (int j = ; j < LEN + ; j++)
{
sa[j] = '\0';
sb[j] = '\0';
if (j < LEN)
{
a[j] = ;
b[j] = ;
}
c[j] = ;
}

甚至:

memset(sa, '\0', sizeof(sa));
memset(sb, '\0', sizeof(sb));
memset(a, , sizeof(a));
memset(b, , sizeof(b));
memset(c, , sizeof(c));

但为了强调a、b和sa、sb是分开的,就分成了两个循环。为了强调LEN和LENC是无关的(而不是差1的关系),就将a、b和c的初始化分开。而memset()是直接将数组的每个字节设为0,这是与内存有关的,也不能强调将每个元素都设为0(况且这对浮点数组不起作用)。

当然这份代码也有可以优化的地方,例如查找第一个非0位可以用二分法:

int sl = ;
int sr = LENC - ;
while (sl + < sr)
{
int sm = (sl + sr) / ;
if (c[sm] != )
sr = sm; // sm为非0位时,说明第一个非0位在sm或sm前面
else
sl = sm; // sm不为非0位时,说明第一个非0位在sm后面
}

Final code #2

这份代码直接在计算A+B时算出C的长度,打印时不需要检查第一个非0位了。

#include <stdio.h>
#include <string.h> #define LEN 1000
#define LENC 1001 void convert(const char s[], int len, int a[]);
void add(const int a[], int la, const int b[], int lb, int c[], int * plc); // 多了plc参数
void print(const int c[], int lc); // 多了lc参数 int main()
{
int t;
char sa[LEN + ], sb[LEN + ];
int la, lb, lc; // 声明了lc用来表示C的长度
int a[LEN], b[LEN], c[LENC]; scanf("%d", &t); for (int i = ; i < t; i++)
{
for (int j = ; j < LEN + ; j++)
{
sa[j] = '\0';
sb[j] = '\0';
}
for (int j = ; j < LEN; j++)
{
a[j] = ;
b[j] = ;
}
for (int j = ; j < LENC; j++)
c[j] = ;
scanf("%s%s", sa, sb);
la = strlen(sa);
lb = strlen(sb);
printf("Case %d:\n%s + %s = ", i + , sa, sb);
convert(sa, la, a);
convert(sb, lb, b);
add(a, la, b, lb, c, &lc);
print(c, lc);
printf("\n");
if (i < t - )
printf("\n");
} return ;
} void convert(const char s[], int len, int a[])
{
for (int i = ; i < len; i++)
a[LEN - len + i] = s[i] - '';
} void add(const int a[], int la, const int b[], int lb, int c[], int * plc)
{
int lc = (la > lb) ? la : lb;
int g = ;
for (int i = LEN - ; i >= LEN - lc - ; i--)
{
c[i + LENC - LEN] = a[i] + b[i] + g;
g = c[i + LENC - LEN] / ;
c[i + LENC - LEN] %= ;
}
// 保存C的长度
*plc = lc;
// 如果max{la, lb} + 1位非0,则长度+1
if (c[LENC - lc - ] != )
(*plc)++;
} void print(const int c[], int lc)
{
// 直接从LENC - lc处开始打印
for (int i = LENC - lc; i < LENC; i++)
printf("%d", c[i]);
}

[HDU1002] A + B Problem II的更多相关文章

  1. HDU1002 -A + B Problem II(大数a+b)

    A + B Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  2. hdu1002 A + B Problem II(高精度加法) 2016-05-19 12:00 106人阅读 评论(0) 收藏

    A + B Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. HDU1002 A + B Problem II 大数问题

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1002 A + B Problem II Time Limit: 2000/1000 MS (Java ...

  4. hdu1002 A + B Problem II(大数题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1002 A + B Problem II Time Limit: 2000/1000 MS (Java/ ...

  5. hdu1002 A + B Problem II[大数加法]

    目录 题目地址 题干 代码和解释 参考 题目地址 hdu1002 题干 代码和解释 由题意这是一个涉及到大数的加法问题.去看了一眼大数加法的方法感觉头很大,然后突然发现Java可以流氓解决大数问题,毅 ...

  6. (string高精度)A + B Problem II hdu1002

    A + B Problem II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  7. hdu1032 Train Problem II (卡特兰数)

    题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能.    (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...

  8. nyoj 623 A*B Problem II(矩阵)

    A*B Problem II 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述 ACM的C++同学有好多作业要做,最头痛莫过于线性代数了,因为每次做到矩阵相乘的时候,大 ...

  9. HDU 1002 A + B Problem II

    A + B Problem II   Time Limit: 1000MS      Memory Limit: 65536K Total Submissions: 16104    Accepted ...

随机推荐

  1. 论.net平台的切身感触(惑)

    这篇博客只是作者客观看法,不喜勿喷,条条大路通罗马,路不同风景也不一样,接下来的路该怎么走? 简介:作者.net程序员一枚,工作已有四年,接触过.net平台winform,webform,mvc的开发 ...

  2. Elasticsearch搜索之best_fields分析

    顾名思义,best_field就是获取最佳匹配的field,另个可以通过tie_breaker来控制其他field的得分,boost可以设置权重(默认都为1). 下面从宏观上来讲的简单公式: scor ...

  3. 简单聊聊Storm的流分组策略

    简单聊聊Storm的流分组策略 首先我要强调的是,Storm的分组策略对结果有着直接的影响,不同的分组的结果一定是不一样的.其次,不同的分组策略对资源的利用也是有着非常大的不同,本文主要讲一讲loca ...

  4. CSAcademy Beta Round #5 Long Journey

    题目链接:https://csacademy.com/contest/arhiva/#task/long_journey/ 大意是有一张无向不带权的图,两个人同时从s点出发,分别前往a点和b点,且每个 ...

  5. 利用Unity3D实现多平台增强现实网络游戏的一种方案

    这几天去厦门参加了VALSE2017会议,对于其中某个环节展示的有关增强现实游戏的部分印象深刻.因为前两年一度沉迷于利用各类引擎开发游戏,所以也曾经以Pokemon GO为模板开发过一款多平台增强现实 ...

  6. Web.简单配置

    XML 元素不仅是大小写敏感的,而且它们还对出现在其他元素中的次序敏感.所有这些元素都是可选的.因此,可以省略掉某一元素,但不能把它放于不正确的位置. icon icon元素指出IDE和GUI工具用来 ...

  7. JS中Object常用的一些属性和方法

    1⃣️属性 刚接触prototype.constructor.proto这三个玩意儿的时候,是不是有点儿傻傻分不清楚的感觉?下面来简单的说下... 举

  8. lxml简明教程

    最近要做下微信爬虫,之前写个小东西都是直接用正则提取数据就算了,如果需要更稳定的提取数据,还是使用 xpath 定位元素比较可靠.周末没事,从爬虫的角度研究了一下 python xml 相关的库. P ...

  9. 蓝桥杯-趣味算式-java

    /* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...

  10. Hadoop化繁为简-从安装Linux到搭建集群环境

    简介与环境准备 hadoop的核心是分布式文件系统HDFS以及批处理计算MapReduce.近年,随着大数据.云计算.物联网的兴起,也极大的吸引了我的兴趣,看了网上很多文章,感觉还是云里雾里,很多不必 ...