大数的阶乘之数组方法

1042 N! 大数的阶乘


Problem Description
Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!
Input
One N in one line, process to the end of file.
Output
For each N, output N! in one line.
Sample Input
1
2
3
Sample Output
1
2
6


题目是1万的阶乘,那也是大数了吧,普通的数据类型也只能存储30的阶乘都会超限,更何况10000呢?因为之前敲了大数加减乘法,所以一看到这题就准备朝着方便去想,但越想就越觉得复杂,后来还是请教学长敲出来的,毕竟我们还是见识少啊,(做题太少,见识面不广啊),


下面来介绍思路;
这种思路是储存几位数用一个数组元素存储下来,从而达到大数相乘的结果。我们先看看如果一个数组元素只存储一位的话,是怎么样子的,我们先模拟8*9*10吧。


8*9=72,则有两个数组元素存储他们,分别存储7和2,然后怎么与10来乘呢?没错直接乘,这里也要进位的。2*10=20;则会保留0,进2;7*10=70,保留0进7,可以看出这次就有三个数组元素了,7,2,0,看结果8*9*10是不是720;
没错这题就是这种算法;只是一个数组元素存储一位会有点麻烦,因为这里是到10000的阶乘,如果用一个数组元素存储一位的话,那么可能一下要进4位,一下子就麻烦了。所以我们干脆四位一存,因为这里恰好是最多进四位,那么我们四位一存是不是简单多了。四位一存和1位一存这种思路是一样的。


现在我们就准备敲代码了,然而这种思路怎么代码化呢。感觉没什么头绪啊,怎么一个数组元素存储4个数字呢?想不通了。汗,还是见识太少了啊。现在来分析吧。先看刚才的事例,是不是2要乘以10并要考虑是否进位,7也一样的,也要乘以10,


也要考虑进位问题,在就应该有点代码的思路了吧,起码有个循环来是数组元素的每个数都要乘以接下来的数i。并且循环里面还要有if的判断,判断是否进位。当然还要在这个循环外面判断数组下标是否要增加。


现在是不是很明确了,两个循环,一个是控制阶乘,另外一个是来控制每位数组元素的乘法的。还要加判断,一个是判断是否进位,还有一个是来控制数组下标是否要增加。


现在还要注意的一点是四位一存我们要怎么输出,如果单纯以%d输出每个数组元素那么就会出现问题如果中间有个元素是0001;那么他只会输出1而中间的0会不输出但我们却要他输出,因此我们要以%04d输出,输出4个字节不足4个字节的以前导0输出。这里还要注意最高位数对应的数组应该要单独以%d输出。


细节说完了,敲代码的思路也说完了,现在就可以敲代码了。还有一点这个思路可不可以应用到大数乘法里面去呢?这个要去实践一下。


#include<stdio.h>
#include<string.h>
int main()
{
int n, t, i, j, k, f, a[10000];
while(scanf("%d",&n) != EOF){
memset(a, 0, sizeof(a));//初始化0; 
t = 1; 
a[1] = 1;
for(i = 1; i <= n; i++){//n的阶乘,从1到n 
k = 0;
for(j = 1; j <= t; j++){//数组存储(四位一存); 
a[j]=a[j]*i+k;
  k=a[j]/10000;
  a[j]=a[j]%10000;
}
if(k != 0){//数组下标增加 (到达四位一移); 
t++;
a[t]=k;
}
}
printf("%d",a[t]);//最高位不需要考虑是否前导0; 
for(i = t-1; i > 0; i--){
printf("%04d",a[i]);//四位一存则要考虑前导0的清楚 
}
printf("\n");
}

return 0 ;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值