P1009 [NOIP1998 普及组] 阶乘之和

目录

前言:

题外话:

前置知识:

P1601 A+B Problem(高精)

P1303 A*B Problem

AC代码:

P1009 [NOIP1998 普及组] 阶乘之和https://www.luogu.com.cn/problem/P1009


前言:

题目:P1009 [NOIP1998 普及组] 阶乘之和
链接:P1009 [NOIP1998 普及组] 阶乘之和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

虽然这题  n <= 50,但阶乘本身就是很大的数,何况该题求的是阶乘之和,这就必须用到高精度了,高精度乘法和高精度加法

该篇文章有高精度加减法代码高精度加法和高精度减法-CSDN博客

题外话:

这一题可废了我老命了,去把高精度复习了一遍,然后把两题过了,再写这一题,绕死我了,数组有点多🤯🤯::>_<::

前置知识:

P1601 A+B Problem(高精)


https://www.luogu.com.cn/problem/P1601

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <deque>
#include <functional>
#include <climits>

#define quickio ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl "\n"

using namespace std;
typedef long long ll;
//a + b = c

int A[505];//第一个加数的数组
int B[505];//第二个加数的数组
int C[506];//和的数组
int len_c;

void Add()
{
	for (int i = 0; i < len_c; i++)
	{
		C[i] += A[i] + B[i];
		C[i + 1] += C[i] / 10;
		C[i] %= 10;
	}

	if (C[len_c])
		len_c++;
}

int main()
{
	string a, b;//注意用字符串读入
	cin >> a >> b;

	int len_a = a.size(), len_b = b.size();
	len_c = max(len_a, len_b);
	for (int i = 0; i < len_a; i++)
		A[len_a - 1 - i] = a[i] - '0';//注意 - ‘0’,且逆序存
	for (int i = 0; i < len_b; i++)
		B[len_b - 1 - i] = b[i] - '0';//注意 - ‘0’

	Add();

	for (int i = 0; i < len_c; i++)
		cout << C[len_c - 1 - i];//注意逆序输出,因为存的时候是逆序的
	return 0;
}

P1303 A*B Problem


https://www.luogu.com.cn/problem/P1303

int c[5000];
int len_a, len_b, len_c;
void mul(int a[], int b[])
{
	for (int i = 0; i < len_a; i++)
	{
		for (int j = 0; j < len_b; j++)
		{
			c[i + j] += a[i] * b[j];//注意是 +=
			c[i + j + 1] += c[i + j] / 10;
			c[i + j] = c[i + j] % 10;
		}
	}

	while (len_c > 1 && c[len_c - 1] == 0)
	//注意要len_c > 1,如果乘积为0,就会一直减下去,最后什么都不输出,这是错误的
	//注意是c[len_c - 1] == 0
		len_c--;
}

int main()
{
	string a, b;
	cin >> a >> b;
	len_a = a.size(), len_b = b.size();
	len_c = len_a + len_b;
	int aarr[2005], barr[2005];

	//倒着存
	for (int i = 0; i < len_a; i++)
		aarr[i] = a[len_a - 1 - i] - '0';//记得 - '0'
	for (int i = 0; i < len_b; i++)
		barr[i] = b[len_b - 1 - i] - '0';
	
	mul(aarr, barr);

	//cout << len_c << endl;
	//倒着输出
	for (int i = 0; i < len_c; i++)
		cout << c[len_c - 1 - i];
	return 0;
}

AC代码:

P1009 [NOIP1998 普及组] 阶乘之和

P1009 [NOIP1998 普及组] 阶乘之和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

注意该题数据一定会很大,要用到高精度

#include <iostream>
#include <cstring>
#include <algorithm>

#define quickio ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define endl "\n"

using namespace std;
typedef long long ll;

const int N = 1005;

//a*b=c
int A[N];//i
int	C[N];
int jc[N][N];//阶乘数组
int ans[N][N];//答案数组

int main()
{
	int n;
	cin >> n;
	jc[0][0] = 1;//0的阶乘 = 1
	int len_a = 1, len_b = 1, len_c = len_a + len_b, len_ans;
	jc[1][0] = 1;
	ans[1][0] = 1;
	for (int i = 2; i <= n; i++)
	{
		//得到i的数组:A
		int temp = i;
		len_a = 0;
		for (int j = 0; temp; j++)
		{
			A[j] = temp % 10;
			temp /= 10;
			len_a++;
		}

		//高精度乘法:求阶乘(i * (i - 1)!)
		len_c = len_b + len_a;
		for (int j = 0; j < len_a/*i的长度*/; j++)
		{
			for (int k = 0; k < len_b/*上一个阶乘的长度*/; k++)
			{
				jc[i][j + k] += A[j] * jc[i - 1][k];//i * (i - 1)!
				jc[i][j + k + 1] += jc[i][k + j] / 10;
				jc[i][j + k] %= 10;
			}
		}
		while (len_c > 1 && jc[i][len_c - 1] == 0)
			len_c--;

		len_b = len_c;//更新阶乘长度

		//高精度加法:求答案(ans[i-1] + jc[i])
		len_ans = max(len_ans, len_c);
		for (int j = 0; j < len_ans; j++)
		{
			ans[i][j] += ans[i - 1][j] + jc[i][j];
			ans[i][j + 1] += ans[i][j] / 10;
			ans[i][j] %= 10;
		}
		if (ans[i][len_ans])
			len_ans++;

	}

	for (int i = 0; i < len_ans; i++)//逆序输出答案
		cout << ans[n][len_ans - 1 - i];
	return 0;
}

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

脑子不好的小菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值