The factorial algorithm involves two aspects: high-precision calculation and number theory.
I. High-Precision computing factorial
This is actually the least technical problem, but it is often used, so you have to write and optimize its computing.
First, let's look at the factorial calculation of less than or equal to 12 (the calculation result will not exceed the 32-bit range ):
Int factorial (int n ){
If (n = 1 | n = 0)
Return 1;
Return factorial (n-1) * n;
}
This recursive program is simple, clear, and intuitive. However, if n> 12 is used, an error occurs in the range of 32-bit int type, therefore, the above recursive program is only suitable for the factorial calculation of n <= 12. In order to calculate the factorial of n greater, the high-precision Multiplication Algorithm must be included in the factorial calculation, the high-precision multiplication process can be described as follows: (A * B = C, A [0], B [0], and C [0] respectively store the length)
For (I = 1; I <= A [0]; I ++)
For (j = 1; j <= B [0]; j ++ ){
C [I + J-1] + = A [I] * B [j]; // current I + J-1 bit ing + A [I] * B [j]
C [I + j] + = C [I + J-1]/10; // its last digit + its quotient (carry)
C [I + J-1] % = 10; // It can be acquired again
}
C [0] = A [0] + B [0];
While (C [0]> 1 & C [C [0] = 0) C [0] --; // returns the actual length of C by removing the first 0.
With this high-precision multiplication, the calculation of factorial can be carried out through simple iteration:
For (I = 2; I <= n; I ++ ){
Converts I to a character array;
Perform high-precision multiplication: multiply the last result by I
}
2. Related to Number Theory
As the factorial grows at the end, the clever use of number theory to obtain interesting numbers (numbers) and so on becomes the design point of the factorial algorithm. The following are some related problems and analysis:
(1) Calculate the first non-0 number at the end of a factorial:
This is a classic problem. A complicated algorithm uses a difficult mathematical formula. Unfortunately, I won't. I learned from the online materials and sorted out the following simple and easy-to-understand algorithm:
Observe n !, We can find that in the multiplication process, for any n> 1, n! The first non-zero number at the end of is an even number. We only need to keep the last non-zero number. When the number to be multiplied contains a factor of 5, we can multiply all the factors of 5 as 8. This is because:
... X2 * 5 =... 10 (homes) or... 60. The last digit is 6. In contrast, 2*8 = 16, and the last digit is 6.
... X4 * 5 =... 70 (homes) or... 20. The last non-zero number is 2. 4*8 = 32, and the last digit is 2.
... X6 * 5 =... 30 (homes) or... 80. The last non-zero number is 8. 6*8 = 48, and the last digit is 8.
... X8 * 5 =... 90 (homes) or... 40. The last non-zero number is 4. In contrast, 8*8 = 64, and the last digit is 4.
(For n> 1, the last one will not show 1, 7, 3, 9, but will always be 2, 4, 6, 8 cycles)
Therefore, when performing iterative multiplication, we mainly calculate the number of Factor 5, at the same time, we can see that the number of Factor 5 takes 4 as the cycle section (that is, we only need to take the number of it for the 4 modulo ). For the number of factors 5 in different situations, you can use res [5] [4] = {0, 0, 0 }, {6, 8,}, {8, 4,}. The nonzero [I] is used to represent the last digit of the factorial of I:
If t is an even number, multiply: nonzero [I] = (nonzero [I-1] * t) % 10.
Otherwise nonzero [I] = res [(nonzero [I-1] * t) % 10)/2] [five];
Where t is the result of removing all Factor 5, and five is the model of Factor 5 number to 4.
(2 ). Number of zeros at the end of a factorial
The analysis found that, in fact, the end is 0, which is the number of Factor 5, and the calculation is 1 ~ A simple algorithm that contains the number of factors I between n is:
Cnt = 0; while (n) {n/= I; cnt + = n ;}
Therefore, replace I with 5 to get the number of Factor 5, that is, n! The number of zeros at the end.
(3 ). Returns the second number on the left of the factorial.
Simple Algorithm: Use a real number to multiply. If it exceeds 100, divide it by 10. Finally, use a single digit. Because the digits in the integer part are the second digits on the left of the factorial result. Related questions:
(4 ). Judge whether the value m can divide n!
Algorithm: using the prime factor Embedding Method
A. First, directly output two special cases:
M = 0 then 0 will certainly not divide n !;
N> = m, then m can certainly divide n !;
B. then there is only the last case: m> n. We start from the smallest prime factor of m. If we set the prime factor to I, then we can obtain the number of prime factor I of m nums1; check the closed interval I ~ The number between n, the total number of prime factor I, can be simply calculated using the mathematical formula described in (2) above to obtain nums2. If nums2 <nums1, it indicates 1 ~ Number of prime factors contained in n <divisor m contains the number of prime factor I, then m cannot divide n !, Set OK to false.
C. Final: If! OK or m> n or m = 0, the entire division is not allowed; otherwise, the entire division is allowed.
(5 ). Whether the number N represents the sum of several different factorial:
Here we can select the factorial: 0! ~ 9 !, In fact, this question is irrelevant to number theory and related to search.
Analysis, because the number of available factorial is small, you can directly use DFS search to do the following:
A. First, set 0 ~ The factorial of 9 is used as A table A [10], and an array ans [N] that can form the "and" is set.
B. Deep priority search method:
Search (n ){
For (I = n; I <= 9; I ++ ){
Sum + = A [I]; // sum
If sum does not exist in the ans array, insert sum into the ans [] array.
Search (n + 1 );
Sum-= A [I]; // backtracking
}
}
C. Finally, for input n, find whether n exists in the ans array. If n exists, it indicates that n can be expressed as different factorial and; otherwise, it cannot.