蓝桥杯基础练习VIP-阶乘计算(C语言)

题目描述

输入一个正整数n,输出n!的值。

其中n!=1*2*3*…*n。

算法描述

n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。

将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。

首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。

输入格式

输入包含一个正整数n,n< =1000。 

输出格式

输出n!的准确值。

样例输入

10 

样例输出

3628800

思路

用递归的方法将n的阶乘的每个数字相乘,用高精度计算得到带有结果的数组

设立递归函数,将乘数与高精度数组每一位相乘,得到结果的个位保留在数组内,超出个位的部分存储起来,加入到下一位的计算中,计算完毕后递归到下一位乘数,最终返回数组位数

我的函数内将乘数按位数分成了数组,再分别计算,其实不用这一步,将乘数直接与高精度数相乘就可以,在计算的范围内,而且简单方便

起始代码

#include<stdio.h>

int compute(int* a, int k, int n) {
	if (k == 1||k==0)
		return n;//返回位数
	int i, j;
	int b[4];//现有数字高精度表示
	int c[10000] = { 0 };//记录相乘后的结果
	int thisK = k;
	int thisN = n;//记录结果的位数
	int carry = 0;//记录进位
	int thisI = 0;//记录这个数的位数

	while (thisK > 0) {//将数字按位数拆成数组
		b[thisI] = thisK % 10;
		thisK /= 10;
		thisI++;
	}
	for (i = 0;i < thisI;i++) {//位数依次相乘
		carry = 0;
		for (j = 0;j < n;j++) {//两数组相加
			c[i + j] = c[i + j] + b[i] * a[j] + carry;
				carry = c[i + j] / 10;//进位
				c[i + j] = c[i + j] % 10;//当前值
		}
		if (carry > 0) {//最大一位超出
			c[i + j] += carry;
			carry = 0;
			j++;
		}
		if (i + j > thisN) {//最高位数
			thisN = i + j;
		}
		
	}
	
	for (i = 0;i < thisN;i++) {
		a[i] = c[i];
	}
	return compute(a, k - 1, thisN);
}

int main() {
	int n;
	int a[10000] = { 0 };
	scanf("%d", &n);
	int i = 0;
	int k = n;
	while (k > 0) {//计入到高精度位中
		a[i] = k % 10;
		k = k / 10;
		i++;
	}
	k=compute(a, n - 1, i);

	for (i = k - 1;i >= 0;i--) {
		printf("%d", a[i]);
	}
	return 0;
}

优化后的结果

#include<stdio.h>

int compute(int* a, int k, int n) {
	if (k == 1||k==0)
		return n;//返回位数
	int i;
	int thisN = n;//记录结果的位数
	int carry = 0;//记录进位
	
	for (i = 0; i < n; i++) {
		a[i] = a[i] * k + carry;

		carry = a[i] / 10;//总体进位
		a[i] = a[i] % 10;//这一位的结果
	}
	while (carry>0) {//进位
		a[thisN] = carry % 10;
		carry /= 10;
		thisN++;
	}

	return compute(a, k - 1, thisN);
}

int main() {
	int n;
	int a[10000] = { 0 };
	scanf("%d", &n);
	int i = 0;
	int k = n;
	while (k > 0) {//计入到高精度位中
		a[i] = k % 10;
		k = k / 10;
		i++;
	}
	k=compute(a, n - 1, i);

	for (i = k - 1;i >= 0;i--) {
		printf("%d", a[i]);
	}
	return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值