(高精度自定义大整数Bigint)洛谷P1591 阶乘数码

前言

  趁热打铁!有了Bigint模板的力量,胜利是必然的。

题目概述

在这里插入图片描述

AC代码

#include<iostream>
#include<cstring> 
using namespace std;
#define maxn 100010
struct Bigint
{
	int len, a[maxn];
	Bigint(int x = 0)
	{
		memset(a, 0, sizeof(a));
		for (len = 1; x; len++)
			a[len] = x % 10, x /= 10;
		--len;
	}
	int &operator[](int i)
	{
		return a[i];
	}
	void flatten(int L)
	{
		len = L;
		for (int i = 1; i <= L; ++i)
		{
			a[i + 1] += a[i] / 10; a[i] %= 10;
		}
		for (; !a[len];)
			len--;
	}
	void print()
	{
		for (int i = max(len, 1); i >= 1; --i)
			printf("%d", a[i]);
	}
};
Bigint operator+(Bigint a, Bigint b)
{
	Bigint c;
	int len = max(a.len, b.len);
	for (int i = 1; i <= len; ++i)
		c[i] += a[i] + b[i];
	c.flatten(len + 1);
	return c;
}
Bigint operator*(Bigint a, int b)
{
	Bigint c;
	int len = a.len;
	for (int i = 1; i <= len; ++i)
		c[i] = a[i] * b;
	c.flatten(len + 11);
	return c;
}
int main()
{
	int q;
	cin>>q;
	while(q--)
	{
		int n,num;
		scanf("%d%d",&n,&num); 
		Bigint fac(1);
		for(int i=1;i<=n;++i)
		fac=fac*i;
		long long ans=0;
		for(int i=1;i<=fac.len;++i)
		{
			if(fac[i]==num)
			++ans;
		}
		printf("%lld",ans);
		puts("");
	}
	return 0;
}

分析思路

1.如果这题数据不是很大的话,其实是一道很简单的题目对吧,阶乘,再求和,这个相信大家都是会做的。然就坏在数据很大上,大到连long long都存不下了,所以我们要接入高精度使用。

2.这里采用了洛谷《深入浅出程序竞赛》的一种写法,众所周知嘛,高精度的题目C++最吃亏,JAVA有大整数类,Python默认无穷大,那么我们可以仿照JAVA,自己实现一个大整数Bigint类。把这个大整数类的模板单独贴一次==(注意因为模板里使用了memset函数,所以要引入库文件cstring/string.h== :

#define maxn 1000
struct Bigint
{
	int len, a[maxn];
	Bigint(int x = 0)
	{
		memset(a, 0, sizeof(a));
		for (len = 1; x; len++)
			a[len] = x % 10, x /= 10;
		--len;
	}
	int &operator[](int i)
	{
		return a[i];
	}
	void flatten(int L)
	{
		len = L;
		for (int i = 1; i <= L; ++i)
		{
			a[i + 1] += a[i] / 10; a[i] %= 10;
		}
		for (; !a[len];)
			len--;
	}
	void print()
	{
		for (int i = max(len, 1); i >= 1; --i)
			printf("%d", a[i]);
	}
};
Bigint operator+(Bigint a, Bigint b)
{
	Bigint c;
	int len = max(a.len, b.len);
	for (int i = 1; i <= len; ++i)
		c[i] += a[i] + b[i];
	c.flatten(len + 1);
	return c;
}
Bigint operator*(Bigint a, int b)
{
	Bigint c;
	int len = a.len;
	for (int i = 1; i <= len; ++i)
		c[i] = a[i] * b;
	c.flatten(len + 11);
	return c;
}

3.注意到这个大整数类给我们提供了很重要的两种算式,高精+高精,以及高精乘低精(我之前说过,乘法更多考的不是高精乘高精)。可以说是非常实用了。然而,如果真的出现其他情况怎么办呢?(比如取余/乘方)等运算?别急,之后的题目会具体介绍
4.引入大整数类后,我们就可以像使用int一样使用Bigint,仅仅在初始化和打印的时候略有区别,那么这道题便不难了。墙裂建议大家都背下这个模板!

5.前四点嘛,和之前的那道阶乘之和的题目是一样的。两者没有太大的区别,主要就是用来练习大整数类的写法。(自定义大整数类Bigint)洛谷P1009 阶乘之和

文末广告

学习算法和数据结构真的是个很累的过程,不会做只能求助于题解。 因为写代码这个东西基本上是千人千面。同时网络上搜到的题解很多要么用到的是自己还没学到的知识,看不懂;要么内核过于简陋,只能糊弄当前题目,不具有普适性。
如果你是一个喜欢做洛谷,ACwing和PTA的题目的同学,欢迎关注我的博客,我主要在这三个平台上做题,认为有价值和有难度的题目我会写题解发布出来。

TreeTraverler的往期文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在C语言中,由于整数类型有一定的大小限制,直接计算大整数阶乘可能会导致溢出。为了处理高精度计算,特别是在计算较大数值的阶乘时,通常会使用一些特殊的数据结构算法,比如动态数组(数组或链表)来存储中间结果,并利用迭代或者递归的方式逐步计算。 以下是一个简单的高精度阶乘计算方法(利用数组存储大整数)的示例: ```c #include <stdio.h> #include <stdlib.h> // 定义一个结构体来表示大整数 typedef struct { int* digits; // 数组存储每个位 int size; // 数组长度 } bigint; // 初始化大整数为0 bigint init_zero() { bigint zero; zero.digits = malloc(sizeof(int)); zero.digits = 0; zero.size = 1; return zero; } // 添加两个大整数 bigint add(bigint a, bigint b) { if (a.size == 0) return b; if (b.size == 0) return a; int carry = 0, i, j, new_size; bigint result = init_zero(); for (i = a.size - 1, j = b.size - 1; i >= 0 || j >= 0; --i, --j) { int sum = a.digits[i] + b.digits[j] + carry; result.digits[result.size++] = sum % 10; carry = sum / 10; } if (carry > 0) result.digits[result.size++] = carry; return result; } // 计算阶乘 bigint factorial(bigint n) { bigint fact = init_zero(), temp = n; while (temp.digits != 0) { fact = add(fact, temp); temp.digits[temp.size - 1]--; if (temp.digits[temp.size - 1] == 0) temp.size--; } return fact; } int main() { bigint num; printf("请输入一个整数: "); scanf("%d", &num.digits); num.size = 1; num = factorial(num); for (int i = num.size - 1; i >= 0; --i) { printf("%d", num.digits[i]); if (i != 0) printf(","); } return 0; } ``` 请注意,这个例子没有处理负数和溢出问题,实际应用中可能需要额外检查。此外,如果频繁进行高精度计算,可能要考虑使用专门的库如GMP(GNU Multiple Precision Arithmetic Library)来提高效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

102101141高孙炜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值