现在我们来探讨一下数论中的大数阶乘问题。
要了解大数阶乘,首先我们来了解一下普通的阶乘的方法。
1.一般来说第一时间想到的就是利用循环或者是递归
简单列一下代码
for(int i=1;i<=n;i++)
ans*=i;
或者
return n*f(n-1);
大家可以思考一下,当n比较大的时候,代码运行的时间会非常大,同时只能计算一个数的阶乘,我计算了10!,但是要求9!的阶乘的话还得再求一遍,数据无法保存,而且又发现10!=9!*10;那么我可不可以开一个数组把每一个数的阶乘都存进去呢?
2.一个简单的递推就可以实现
首先,找到规律,n!=n*(n-1)! 开一个数组a[max];
for(int i=1;i<=n;i++)
a[i]=i*a[i-1];
这里要注意,要给a[0]赋值1;那么利用这个简单的递推理论上来说就可以保存找到任意一个数的阶乘了。
但是实际上,一个数的阶乘会非常大,例如100!=93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
所以一个 64位的 long long 型,数据存不下,这时我们就要提出新的思路来存储 这个数。
既然要存储表示一个数,那我们首先就要思考存储数据的原理
用二进制来举例,00000011,表示为十进制数该如何表示?2^0*1+2^1*1=3;原理为一个数有有权值,用这个权值乘这个位上的数 再相加就表示了一个数。再思考一下,二进制的权值是为2,可以表示2^7的值,那如果权值非常大,100,1000甚至10000呢?我们就可以用一个很小的数表示一个非常大的数,可以思考一下二进制和十进制的相互转化,感兴趣的可以自行实现(我也不太懂)。
3.还有的人可能会想到利用数组来存储.
数用一个字符型数组来表示,数组的每一个元素表示一位十进制数字,高位在前,低位在后。那么,用这种表示法,如何做乘法运算呢?其实这个问题并不困难,可以使用模拟手算的方法来实现。回忆一下我们在小学时,是如何做一位数乘以多位数的乘法运算的。例如:2234*8。我们将被乘数表示为一个数组A[], a[1],a[2],a[3],a[4]分别为2,2,3,4,a[0]置为0。
Step1: 从被乘数的个位a[4]起,取出一个数字4.
Step2: 与乘数8相乘,其积是两位数32,其个位数2作为结果的个位,存入a[4], 十位数3存入进位c。
Step3: 取被乘数的上一位数字a[3]与乘数相乘,并加上上一步计算过程的进位C,得到27,将这个数的个位7作为结果的倒数第二位,存入a[3],十位数2存入进位c。
Step4:重复Step3,取a[i](i依次为4,3,2,1)与乘数相乘并加上c,其个位仍存入a[i], 十位数字存入c,直到i等于1为止。
Step5:将最后一步的进位c作为积的最高位a[0]。
不断利用进位与余位,我们就可以存储一个非常大的数
#include<stdio.h>
#define maxn 10000
//一个数的阶乘非常大 如果用每位进位为10的话 开数组也无法保存很大的数字 所以我们 设定一个最大位数 让每一位的进位 变得很大
int maxn_s(int n) {
int num = 0;
while (n) {
n /= 10;
num++;
}
return num;
}//计算数组一位最多存储的位数 例如num=3 则最多存储999
int fac(int n) {
int len = maxn_s(maxn)-1;//表示数组一个的存储的 范围
int a[maxn] = { 1 };//存大数
int c, num=0;//t表示进位
for (int i = 1; i <= n; i++) //表示n的阶乘
{
c = 0;//每次开始一次乘法前 将进位归零
for (int j = 0; j <=num; j++) //双重循环的意义是 每次乘法都要将数组的每一位乘上这个数
{
a[j] = a[j] * i + c;
c = a[j] / maxn;
a[j] = a[j] % maxn; //保存数据 每次都保存除了 进位 余下的位数
}
if (c > 0)//如果位数不为零 则最大位数 则让最大一位保存进位
{ num++; a[num] = c; }
}
printf("%d".a[num]);
for (int i = num-1; i >= 0; i--) printf("%4.4d", a[i]);
return 0;
}
int main() {
int n;
scanf_s("%d", &n);//求一个数n的阶乘
fac(n);//n的阶乘的函数
return 0;
}