大数问题是一种区别于普通数值问题的特殊问题,当运算的数值过大甚至包括long long int64bit都无法存储时我们就将引用到大数运算思想。
大数问题究其根本其实就是利用数组可以开到远远大于64bit的特性来存储和运算这些过大的结果,比如说一个1000位的数字自然没法使用long long int存储时我们可以考虑将这个1000位的数字拆分开来变成1000个数字,之后我们将这1000个数字像是用笔写在纸上一样每个数字写进一位数组了也就巧妙地玩成了这1000位数字的存储了。
当然刚刚说的只是存储,大数问题与普通数问题很重要的一点区别就是运算我们把两个数组相加自然和两个int型整数相加是不同的,而我们接下来就会通过HDU 1042试探性的学习大数乘法。
附上原题:
Description
Input
Output
题意解读:
输入一个数N,玩成它的阶乘运算(即 1 × 2 × 3 ×……×(N-1)× N )。其中0≤N≤10000。
思路分析:
首先我们应该从N的取值范围判断这到底是一道普通数问题还是一道大数问题,显然当N取10000时,就算是long long int也绝对无法存储这个计算结果,所以这是一道大数问题。
如之前所说,大数问题的思路就是将数字的每一位数拆分出来,m位的大数从而变成m个数字的数组,之后我们要对这个m位数进行计算时我们利用四则运算本身的特性,对每一位数进行计算并完成进位后即是结果了(说白了就是回归小学运算)
源代码:
//AC Memory:1976 KB Time:873 ms
#include<iostream>
#include<string.h>
using namespace std;
int main()
{
int ans[100000], inp, i, j, jw, len;
//我们使用ans数组存储阶乘计算的结果;使用inp来接收input输入值,也就是题目中的N;
//i、j作为循环记录变量;jw意为“进位”,用来进行进位运算;len记录数组长度也就是计算数据的位数;
while (cin >> inp)
{
//初始化部分
memset(ans, 0, sizeof(ans));
ans[0] = 1;
len = 1;
//运算部分
for (i = 1; i <= inp; i++)
{
jw = 0;
for (j = 0; j < len; j++)
{
ans[j] = ans[j] * i + jw;
jw = ans[j] / 10;
ans[j] = ans[j] % 10;
if (j == len - 1 && jw > 0)
{
//如果当前运算到了最高位但是却仍然有进位时,我们应当增加长度len值
//在长度len值增加的同时循环终止条件j<len也就不再满足而继续遍历,我们就完成了进位值的存储了
len++;
}
}
}
//输出部分
for (i = len - 1; i >= 0; i--)
cout << ans[i];
cout << endl;
}
return 0;
}
思路研讨:
其实这段代码有一个明显的不足就是每一次输入一个数它就会从1重新计算阶乘,实际上如果我们可以从一开始就把N的每一种取值的阶乘计算出来并在输入后直接调用需要的答案,时间就会非常有效的得到缩减。这种方法到底能不能实现呢?还请大家自行思考。
如果对我的文章有任何的疑问或者建议,都欢迎留言评论或者私信告诉我,谢谢大家的帮助~