C++蓝桥杯 基础练习之阶乘计算

C++ 蓝桥杯题目讲解汇总(持续更新)


这应该是除了数的读法 (if判断有点烦,以后再花时间去理) 之外,所有的基础练习到此告一段落,接下来需要取学习更多的算法,不断的去提高,向着 蓝桥杯——算法训练环节开冲咯,小白一定会变大白的,奥里给

VIP试题 阶乘计算

资源限制

时间限制:1.0s 内存限制:512.0MB

问题描述

输入一个正整数 n n n,输出 n ! n! n!的值。
  其中 n ! = 1 ∗ 2 ∗ 3 ∗ … ∗ n n!=1*2*3*…*n n!=123n

算法描述

n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数aA[0]表示a的个位,A[1]表示a的十位,依次类推。
  将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
  首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。

输入格式

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

输出格式

输出n!的准确值。

样例输入

10

样例输出

3628800

思路

a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。(由于不知道n!最大多大,我们开个100000长度数组,代表最后的数字长度,不是位数哦)

根据题目的要求,自己将所某一次乘法的计算过程给展示出来,结合代码里注释应该就都能理解了,这里假设当前步骤的大数数组是{0,1,1,1,1,1,0,0,0,…,0}(也可以字符串直接操作),这里为了下标方便多开一些空间了

a[1] a[2] a[3] a[4] a[5] a[6] a[7]
1 1 1 1 1 0 0 0
123 123 123 123 123 0 0 0
3 123+12 123 123 123 0 0 0
5 123+13 123 123 0 0 0
6 123+13 123 0 0 0
6 123+13 0 0 0
6 0+13 0 0
3 0+1 0
1 0
3 5 6 6 6 3 1

如上述表格所示,这个就是在计算阶乘的循环里,大数的计算过程,如下所示:
a [ i ] = ( a [ i − 1 ] + 进 位 ) % 10 (1) a[i]=(a[i-1]+进位)\%10 \tag{1} a[i]=(a[i1]+)%10(1)

a [ i ] 来 自 a [ i − 1 ] 的 进 位 = ( a [ i − 1 ] + ( a [ i − 1 ] 来 自 a [ i − 2 ] 的 进 位 ) ) / 10 (2) a[i]来自a[i-1]的进位 = (a[i-1]+(a[i-1]来自a[i-2]的进位))/10 \tag{2} a[i]a[i1]=(a[i1]+(a[i1]a[i2]))/10(2)

多出来的进位,意味这一次的计算比原来的数大,需要进位,比如最后多出的13的位是比万位高的,分别是百万位,十万位

(博主语言能力表达有限,比较菜菜,见谅呀)

代码–

#include
#include
#define MAX 100000

using namespace std;
int a[MAX];

int main(){
	int n;
	cin>>n;
	
	a[1]=1; //个位的数字是a[1] 
		
	/* 
	x 代表当前的位数(就是表示有多少位)
	y 代表当前的进位,由于每个数组的元素都要乘以一个数,这个数很大,就导致了进位,
	原本数还需要加上进位结果,而x也随着进位y的变化而变化,将每一个y都分配
	好,代表此次乘法结束 
	
	在某一位的进位的话就是进位%10 
	进位到高位的时候,缩小10倍,所以整除 
	*/ 
	int pos_now=1,jw;
	
	for(int i=2;i<=n;i++){
		jw=0;
		for(int j=1;j<=pos_now;j++){
			int t = a[j]*i+jw; //临时的每一位*对应的i的结果,再加上在这个位置的进位就是真实结果 
			a[j] = t%10; //实际a[i]就是t取余 
			jw=t/10; //进位到高位的时候,缩小10倍,所以整除 
		}
		
		//当到当前位数(实际上也是最大)x的时候,多出来的数还要进位
		while(jw){
			a[++pos_now]=jw%10;
			jw/=10;
		} 
			
	}
	for(int i=pos_now;i>=1;i--){
		cout<<a[i];
	}
	return 0;	
}

你可能感兴趣的:(蓝桥杯,算法,c++)