高精度求累加和的问题与解
题目描述:
使用求和公式求1到N的累加和大家都会,但是如果把N值变大呢,比如100位的整数,那该怎么求?
输入格式:
输入在一行中给出1个位数不超过100位的整数N。
输出格式:
对每一组输入,在一行中输出1+2+3+……+N的值。
输入样例:
在这里给出一组输入。例如:
10
输出样例:
在这里给出相应的输出。例如:
55
解题思路:
-
鉴于数字过大,简单的使用循环进行前N项和的求解显然是不可解的,因此,很容易想到使用高斯求和公式对简单的1+2+3+…+n问题求解(即等差数列前N项和公式)。
-
涉及相关知识:
高精度乘法、高精度数除低精度数。
代码实现:
#include<iostream>
#include<cstring>
using namespace std;
char A[101] = { '\0' };
int main()
{
cin >> A;
int along = strlen(A);
int a[100] = { 0 }, b[101] = { 0 },sum[220] = { 0 };
//字符型向整型数组转化,并倒置数组
for (int i = 0; i < along; i++) a[i] = A[along - 1 - i] - 48;
for (int i = 0; i < along; i++) b[i] = A[along - 1 - i] - 48;
//执行首项+末项
b[0]++;
//判断是否发生进位
for (int i = 0; i < along; i++)
{
b[i + 1] += b[i] / 10;
b[i] = b[i] % 10;
}
//计算(首项+末项)*项数
//这里只能确定a数组的长度为along b数组的长度是along还是along+1不确定
//虽然可以通过编写代码确认具体长度,但是,鉴于已经初始化整个数组为0
//我们无妨让最终结果的某一位再加上一个0
for (int i = 0; i < along; i++)
for (int j = 0; j < along + 1; j++)
sum[i + j] += a[i] * b[j];
//判断sum的进位情况
for (int i = 0; i < 220; i++)
{
int tmp = sum[i];
sum[i] = tmp % 10;
sum[i + 1] += tmp / 10;
}
//记录sum的有效长度(去掉前导0)同时,在本题背景中,无需担心最后结果是0。
int sumlen = 220;
while (sum[sumlen - 1] == 0)sumlen--;
//进行除2操作(高精度数除低精度数)
for (int i = sumlen - 1; i >= 0; i--)
{
int temp = sum[i];
sum[i] = temp / 2;
//需要注意:如果是高位余数,我们应该扩大十倍补至下一位(即落位)
if (i > 0)
{
sum[i - 1] += 10 * (temp % 2);
}
//但是,如果余数本身就是个位产生的,我们要记得把余数原原本本地还给个位哟
else if (i == 0)
{
sum[i] = temp / 2;
sum[i] += temp % 2;
}
}
//可惜,当这样做完除法后,我们又无法确定最后的sum有多少位了
//所以,依然要考虑去除前导0的情况
int flag = 0;//利用flag记录是否有过至少一次输出
for (int i = sumlen - 1; i >= 0; i--)
{
if (sum[i] == 0 && flag == 0);
else
{
flag = 1;
printf("%d", sum[i]);
}
}
return 0;
}
后记:
在最后输出前导0时,考虑到最后结果不会为0,,可以更加优化这个去除前导0的步骤
int flag = 0;
for (int i = sumlen - 1; i >= 0; i--)
{
if (sum[i] != 0 || flag != 0)
{
printf("%d", sum[i]);
flag = 1;
}
}
return 0;