C/C++实现洛谷P1009 [NOIP1998 普及组] 阶乘之和 题目(题解)

这道题需要用到高精度加法高精度乘法,本文不会具体讲解这两个东西,只做题目的具体实现,如果还需要复习一下这俩,可以去看眼我之前的文章~

虽然代码是用C++实现的,但是其实没有用到特殊的东西,还是很好改成C形式的

如有问题,欢迎到评论区讨论~

基本步骤:

1.先实现独立的高精度乘法函数

2.再实现独立的高精度加法函数

3.主函数输入n值进行for循环并进行高精度乘法和加法

4.输出最终结果

 单独看高精度加法和高精度乘法的教程,发现都是字符串输入数字,再转成int类型数组存入各个位的值

但是这道题最大值只有50,需要用到高精度的地方是多次相乘后的乘积和后续的加法

所以在最开始放入int数组的时候,不用先转字符串再转入int数组,直接用 数据/10 的方法放入到int数组,所以还需要一个对应的size去记录转入到数组的数的位数

详细代码:

#include<iostream>
#include<cstring>//用到了memset
#define N 100//自定义数组长度,也可自己改成malloc动态分配

using namespace std;

//阶乘用的
//multiplier 乘数
//product 乘积
int mulOne[N] = { 0 };//乘数1
int moSize = 0;//乘数1所存的数的位数
int mulTwo[N] = { 0 };//乘数2
int mtSize = 0;//乘数2所存的数的位数
int product[N] = { 0 };//乘积
int proSize = 0;//乘积所存的数的位数
//求和用的
int sum[N] = { 0 };//和
int sumSize = 0;//和所存的数的位数

//统计已经阶乘过的数,从2开始是因为1的情况可直接输出
int cnt = 2;

void jiecheng(int n) {
	if (n > cnt)cnt = n;//先判断已经阶乘过的数和传入的数的大小关系
	for (int i = cnt; i <= n; i++)//从没阶乘过的数开始
	{
		//将n放入mulTwo
		int temp = i;
		mtSize = 0;//每次都要重置,不然传入的不对
		while (temp)
		{
			mulTwo[mtSize++] = temp % 10;
			temp /= 10;
		}
		//开始相乘(先乘完,不管进位)
		//		one
		//	x	two
		//-------------
		for (int i = 0; i < mtSize; i++)//two
		{
			for (int j = 0; j < moSize; j++)//one
			{
				//双重循环,到后面不能保证 product[i + j] 里 没有 有效数据
				product[i + j] = product[i + j] + mulOne[j] * mulTwo[i];
			}
		}
		//处理进位
		for (int i = 0; i < mtSize + moSize; i++)
		{
			if (9 < product[i]) {
				product[i + 1] = product[i + 1] + product[i] / 10;
				product[i] = product[i] % 10;
			}
		}
		//计算乘积的位数
		int length = mtSize + moSize;
		while (0 == product[length - 1]) {
			length--;
		}
		proSize = length;
		//将此步骤算出来的product给mulOne
		for (int i = 0; i < proSize; i++)
		{
			mulOne[i] = product[i];
		}
		moSize = proSize;
		//清空product,用于下次计算存储结果
		memset(product, 0, sizeof(product));
		proSize = 0;
	}
	//最终的计算结果在mulOne中
	//for (int i = 0; i < moSize; i++)
	//{
	//	cout << mulOne[moSize - 1 - i];
	//}
	//cout << endl;
}

void qiuhe(int sum[N],int mulOne[N]) {
	//找到两个加数的最大位数
	int max = moSize > sumSize ? moSize : sumSize;
	//也是先不管进位相加
	for (int i = 0; i < max; i++)
	{
		sum[i] = sum[i] + mulOne[i];
	}
	//处理进位
	for (int i = 0; i < max; i++)
	{
		if (9 < sum[i]) {
			sum[i + 1] = sum[i + 1] + sum[i] / 10;
			sum[i] = sum[i] % 10;
		}
	}
	sumSize = max;
	if (0 == sum[sumSize-1]) {
		sumSize--;
	}
	//for (int i = 0; i < sumSize; i++)
	//{
	//	//cout << sum[sumSize - 1 - i];
	//}
	//cout << endl;
}

int main() {
	int n;
	cin >> n;
	//对最开始的阶乘赋初值
	mulOne[0] = 1;
	moSize = 1;
	//开始计算
	for (int i = 1; i <= n; i++)
	{
		jiecheng(i);
		qiuhe(sum, mulOne);
	}
	//输出最终结果
	for (int i = 0; i < sumSize; i++)
	{
		cout << sum[sumSize - 1 - i];
	}
	return 0;
}

优化:

搞懂之后会发现,阶乘函数中最外层的循环其实可以去掉

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值