蓝桥杯:基础练习 阶乘计算
问题描述
输入一个正整数n,输出n!的值。
其中n!=123*…*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
思路
- 逐位相乘
- 处理进位
坑
需要注意的是,对于最高位的进位处理,不止进行一次!
原因:可能最高位是一个很大的数
比如1234,那么进位之后,最高位是123,次高位是4
但是如果是12345678987654321,进位后最高位是1234567898765432,次高位是1,那么下一次乘法的时候,最高位乘上阶乘的那个数,最高位会溢出,即使用long long 也会 !!!
多次对高位进位
while(a[len-1] > 9)
{
a[len] = (a[len-1] - a[len-1]%10)/10;
a[len-1] = a[len-1] % 10;
len += 1;
}
如果没有多次进位
会发现最高位非常大以至于溢出
AC完整代码
#include <iostream>
using namespace std;
typedef long long ll;
#define maxlen 1000000
ll a[maxlen];
ll len;
// 乘法,当前数 * x
void mul(ll x)
{
// 逐位相乘
for(ll i=0; i<len; i++)
{
a[i] *= x;
}
// 处理进位
for(ll j=0; j<len-1; j++)
{
a[j+1] += (a[j] - a[j]%10)/10;
a[j] = a[j] % 10;
}
// 注意此处,需要 while 多次处理
while(a[len-1] > 9)
{
a[len] = (a[len-1] - a[len-1]%10)/10;
a[len-1] = a[len-1] % 10;
len += 1;
}
}
void out()
{
for(ll i=len-1; i>=0; i--)
{
cout<<a[i];
}
cout<<endl;
}
int main()
{
a[0] = 1;
ll n;
len = 1;
cin>>n;
for(ll i=2; i<=n; i++)
{
mul(i);
}
out();
return 0;
}