It computes a factorial as a very large integer in the (int_array[]) variable, then computes the sum of digits in the (sum) variable. (That's at the end. The (sum) variable is also used for temporary results in the
1. Integer division of unsigned numbers (and positive signed numbers) is defined to truncate the quotient, if needed, toward 0. That means that 24/5 = 4. It works just like grade-school quotient-and-remainder division, where a/b is the quotient of a divided by b, and a%b is the remainder. So, if:
q = a/b .... and
r = a%b
then a == q*b + r
Now, it's simple algebra. If a == q*a + r, then r = a - q*b. But r is a%b, and q is a/b, so:
r == a - q*b
a%b == a - (a/b)*b
That's basic enough that it's the formal definition of what the % operator does, even with signed integer types where the rounding direction is implementation-dependent. So, substitute sum for a and 100000 for b and you get your result:
sum%100000 == sum - (sum/100000)*100000
2. The arithmetic into the int_array[] array is much like grade-school arithmetic, too, only the "digits" are in base 100000. When you multiply two digits, the result may be larger than a single digit. You handle that by writing down the ones digit, and "carrying" the tens digit. If you add:
product = a * b .... where a and b are digit values from 0 to 9
the ones digit of product is (product%10) and the carry is (product/10). The same idea is used to multiply in "base 100000", by storing sum%100000 and carrying (sum/100000) to the next iteration of the loop. The sum variable at entry to the for(j) loop is the carry-in from the preceding digit position, and the first statement makes it equal to (carry-in) + (digit j of big number)*(i). That is, it's i times the next digit, plus whatever was "carried from the right".
3. In a printf format, %d is for (signed) *decimal*. (You'd use %u for unsigned decimal formatting, or %x for hexadecimal. Read the docs for more information.) The 5 is the minimum width to format. If the formatted result is smaller, it is right-adjusted in a 5-position field. The 0 in front of the width says to pad with zeros on the left instead of spaces. A number like 123 in the array would normally format as only three characters, but with %05d formatting it will display as 00123 instead. That's exactly what you want for all but the very leftmost digit (which is formatted with just %d, outside the loop, to suppress leading zeros for that group of base-ten digits only.)
Summary:
The base-100000 "digits" are stored in the int_array[] variable with the ones digit in int_array[0], the 100,000s digit in int_array[1], the 10,000,000s digit in int_array[2] and so on. The variable k is the index of the highest-order digit currently in the array.
In the for(i) loop, i is the muliplier 2, 3, 4, ..., (input) Each iteration multiplies int_array[] by i.
The for(j) loop multiplies one digit of int_array by i, adds the previous carry, stores the low "digit" of the result back into the current digit position, and computes the carry into the next position.
The while(sum>0) loop increases the size of the number in int_array[] when there is a carry out of the highest previous position.
The standalone printf() prints the label and leftmost digits.
The for(z) loop prints out the remaining digits, preserving interior zeros (as noted above).
The final for(i) loop computes the sum of the decimal digits of int_array[]. In each iteration, z is one "base 100000" digit of int_array, with up to 5 nonzero digits.
The while(z) loop (which means "while (z != 0)" in standard C/C++) is a classic loop, using the ideas above, to add the decimal digits of a non-negative integer value. Standard C/C++ doesn't define exactly what it does for negative values, but that doesn't happen here.
- - - -
A final (patriotic?) note: As written, the int_array[] will hold any whole number up to 5000 digits (1000 positions, 5 decimal digits in each position.) The first factorial to overflow this is 1776!.