Title: Factorial Calculation Upgraded Version Author: Chen Yue, Zhejiang University
This question requires the implementation of a function that prints non-negative integer factorials.
Function interface definition:
void Print_Factorial ( const int N );
whereN
is the parameter passed in by the user, and its value does not exceed 1000. If N
is a non-negative integer, the function must print out the value of N
! in one line, otherwise print "Invalid input".
Sample Referee Test Procedure:
#include <stdio.h>
int Factorial( const int N );
int main()
{
int N, NF;
scanf("%d", &N);
NF = Factorial(N);
if (NF) printf("%d! = %d\n", N, NF);
else printf("Invalid input\n");
return 0;
}
/* 你的代码将被嵌在这里 */
Input example:
15
Output sample:
1307674368000
Idea: The last test point of this question is a pit. If you want to pass the last test point, you cannot use ordinary int or long long to store the calculated factorial, because it will cross the boundary!
Our idea is to use an array F[N] to store the factorial (the minimum array length here is set to N=2568. This length is the minimum array length I tried that can just pass the last test point. It doesn’t matter if you write more) . The stored structure is low-order bit first, that is, F[0] stores the ones bit, and so on.
When calculating the factorial, we use an outer loop to iterate i from 2 to N, and multiply F " by " i for each iteration.
Here, "multiplying" the array by a number is done using an inner loop, which is based on the multiplication of integers with carry that we learned in elementary school. To traverse from F[0] to F[N-1], for example, to a certain F[j], we need to perform the following three steps:
(1) Give F[j] Multiply the current i in the outer loop, add the carry value of the previous item in F[j], and then assign the result to F[j], that is, F[j]=F[j]*i+carry;< /span> (3) F [j] only retains single digits, F[j] = F[j]%10.
(2) Calculate the value to be carried to the next bit F[j+1], carry = F[j]/10;
For example, as shown below
Suppose we have obtained 12!=479001600 and now want to calculate 13!. First, we arrange 479001600 in the array F from low to high, which is the first row in the picture above. Then multiply each bit of the array F by 13. For example, we have now calculated the position F[2]. We get 78 from F[2]*13. We go to the ones digit of 78, 7, and add the carry term at this position. 0 (calculated from the previous position), so the result of the new F[2] is 7. Finally, don’t forget to assign the quotient after 78 is divided by 10 to the carry item of the next digit.
When the inner loop is traversed, it is equivalent to multiplying the current factorial F "by" the current i of the outer loop,
When the outer loop is iterated, F stores the factorial we want, but the stored structure is low-order first.
Finally, we need to find the last element of the array that is not 0, and output the array in reverse order starting from this element.
Code:
void Print_Factorial ( const int N ) {
int i, j, carry = 0;
int M = 2568, F[2568] = {1}; // 初始化一个长度为2568的数组,为什么是2568呢?因为刚好能通过最后一个测试点。比2568长,是可以的。
if (N < 0) {
printf("Invalid input");
return;
} else if (N == 0) {
printf("1");
return;
} else if (N > 0) {
for (i = 2; i <= N; i++) { // 用数组F来存放每次迭代算出来的阶乘,存放时低位在前,即F[0]存放的是个位,依此类推。
for (j = 0; j < M; j++) { // 乘的时候,用for循环对数组F的每个元素进行处理,计算的原则就是带进位的乘法。
F[j] = F[j]*i+carry;
carry = F[j]/10;
F[j] = F[j]%10;
}
}
for (i = M-1; i >= 0; i--) {
if (F[i] != 0) {
break;
}
}
for (j = i; j >= 0; j--) {
printf("%d",F[j]);
}
return;
}
}