14

I am working on a Project Euler problem http://projecteuler.net/problem=20.

$n!$ means $n(n - 1)\dots...3.2. 1.$

For example, $10!$ $=$ $10$ $9$ $...$ $3$ $2$ $1$ $=$ $3628800$, and the sum of the digits in the number $10!$ is $3 + 6 + 2 + 8 + 8 + 0 + 0$ $=$ $27$.

Find the sum of the digits in the number $100!$

The crux of the problem is that, the number is just too big for native data types.

I could just use python / ruby or some language that has native large int types, but a lot of these problems have clever little tricks.

My fist thought was just to mod 10 the answer over and over, but checking wolframalpha.com shows me that would only trim $24$ digits from the $158.$

My second thought is to make a little BCD implementation capable of adding and multiplying.

So I did a little research, I cant figure out any way to make the gamma function ant easier than the factorial...

I have run across things like Stirling's Approximation, but it seem calculating that would require more work than it is worth to make super sized functions.

so my question, I suppose: can this problem be digested in a way to be solved using only arbitrarily small numbers?

azimut
  • 24,316
  • This is only an idea (I have no idea if it is plausible or not) but could you not just calculate the number digit by digit, so you can just sum these values? – Andrew D Jul 24 '13 at 14:09
  • If you're going to use wolfralpha, just copy down the result and ad d the digits. In fact, try this directly. – vadim123 Jul 24 '13 at 14:10
  • It's a good question. When I did that question on PE, I used a BigInt object, and coded it in Java. It's a chunky solution, and I'm interested to see where this thread goes and if there's a more elegant solution. – Eric Wich Jul 24 '13 at 14:18
  • Well, in Python you can probably pull it off as a one-liner, it does have native support for large numbers. :) – tomasz Jul 24 '13 at 14:32
  • 1
    See this Meta thread on project Euler problems http://meta.math.stackexchange.com/questions/1090/re-project-euler-questions – GEdgar Jul 24 '13 at 16:08
  • Grady Player: it would be far better if you posted your Project Euler questions at the Project Euler forums. They aren't half-bad! – rschwieb Jul 24 '13 at 17:09
  • He doesn't have access to this problem's forum seeing as he hasn't completed it yet.. @Grady Player, aren't you supposed to figure these out on your own? That's 99% of the fun of Project Euler... – jameselmore Jul 24 '13 at 17:13
  • @jameselmore well I have solved it several different ways now... but none of them are especially good, they are just using python or string math lib or whatever... I just feel like those are sort of cheating... I was looking for something that I didn't understand about numbers that made this task simpler... it seems that since all of the answers are about performing this action in abstracted decimal formats, that there may just not be a better way. – Grady Player Jul 24 '13 at 17:18
  • @GradyPlayer The issue with problems like this is that when you need to compute the sum of digits, you almost always need to resolve what those digits are. So there's no way around having to deal with decimal formats, but there are clever ways to avoid having to use third party libraries, custom routines, or any other such extensions of standard 32-bit arithmetic. – Emily Jul 24 '13 at 17:58

4 Answers4

14

There's got to be a better way.

$100!$ is the product of only 100 small numbers, each of which have an easily found prime factorization. By the Fundamental Theorem of Arithmetic (and commutativity), the prime factorization of $100!$ can be found by "grouping up" like primes from each of its factors' prime factorizations. For example, $8! = 2^3 \cdot 7 \cdot 2 \cdot 3 \cdot 5 \cdot 2^2 \cdot 3 \cdot 2 = 2^7 \cdot 3^2 \cdot 5 \cdot 7$.

Each of the prime factors can be expanded as powers of 10, e.g. $a\times 10^2 + b \times 10 + c$.

From there, it should be more or less straightforward to distribute over powers of 10 to find each individual digit. Add, and done.

I'll see if I can't MATLAB an example... but here's an example for $8!$:

$$\begin{align*} 8! &= 2^7 \cdot 3^2 \cdot 5 \cdot 7\\ &= (1\times 10^2 + 2\times 10 + 8) \cdot 9 \cdot (3\times 10 + 5) \\ &= (9 \times 10^2 + 18 \times 10 + 72) \cdot (3\times 10 + 5) \\ &= ((9+1) \times 10^2 + (8+7)\times 10 + 2) \cdot (3\times 10 + 5) \\ &= (1 \times 10^3 + 1\times 10^2 + 5\times 10 + 2) \cdot (3 \times 10 + 5) \\ &= 3 \times 10^4 + 3\times 10^3 + 15 \times 10^2 + 6 \times 10 + \ldots \\ &\ldots 5\times 10^3 + 5\times 10^2 + 25\times 10 + 10). \end{align*}$$

The last step was the distribution of 35 over the previous terms. Now, group like powers by adding. Any time you get a 2-digit multiple of a power of 10, we shift it's digit over to the next higher power of 10.

$$\begin{align*} 8! &= 3\times 10^4 + 9 \times 10^3 + 12\times 10^2 + 12\times 10 \\ &= 3\times 10^4 + 9 \times 10^3 + 13\times 10^2 + 2\times 10 \\ &= 3\times 10^4 + 10 \times 10^3 + 3\times 10^2 + 2\times 10 \\ &= 4\times 10^4 + 3\times 10^2 + 2\times 10 \\ &= 40320. \end{align*} $$

Now, here's where it gets really cool.

Polynomial multiplication can be thought of as vector convolution, which is the same thing as the Cauchy product. The number 40320 is basically just a polynomial in powers of 10. Pretend momentarily that 10 isn't a number, just a symbol like $x$. Then,

$$40320 = 4 (10)^4 + 0 (10)^3 + 3 (10)^2 + 2 (10)^1 + 0 (10)^0.$$

We can write this in vector form as $[ 4\ 0\ 3\ 2\ 0 ]$.

If we want to then multiply it by something else, say $10 \cdot 9 = 9 (10)^1$ to compute $10!$, then we find the discrete convolution/Cauchy product of the two vectors. I'll leave that up to you, given that it has been pointed out that some folks generally frown on too-complete solutions to PE problems.


The comments to this post are noteworthy. Yes, this is exactly an implementation of a BigInt library. Yes, this is exactly the multiplication algorithm.

In my opinion, however, the purpose of PE isn't to train people how to go find libraries to do their job; it's to discover the underlying mathematics. Hopefully, the relations I've mentioned between Cauchy Products, discrete convolutions, and the multiplication algorithm are interesting -- more interesting than finding a language with BigInt support.

Emily
  • 36,334
  • This is exactly the kind of strategy I was looking for... an example would be nice :), but I may be able to muddle through it. – Grady Player Jul 24 '13 at 15:45
  • 1
    actually once I have the total prime factorization... how do I find the nth digit of 2^68 * 3^45 * 5^16 or whatever it is... – Grady Player Jul 24 '13 at 15:52
  • 2
    I don't see what this strategy buys at all. What you're describing is precisely the traditional multiplication algorithm; it's written in nicely vectorized/distributed notation, but it is the classical algorithm through and through. You might as well skip the prime factorization step and simply do the hundred multiplies this way. (That's not to say that it's a bad approach - just that it's precisely what the OP suggested) – Steven Stadnicki Jul 24 '13 at 16:09
  • Also, you've failed to take into account the fact that the discreet convolution may cause carries, so the intermediate results you hit will be outside the range of $[0..9]$. Since those carries can cause digits to go down as well as up, there's no direct relation (other than the clear mod-9 one) between the digit sum in the convolution and the digit sum in the original product. – Steven Stadnicki Jul 24 '13 at 16:12
  • 3
    @StevenStadnicki Actually, I didn't, because if you get, say, $[ 0\ 14\ 0\ 4\ 5]$ that's the same as $[1\ 4\ 0\ 4\ 5]$. You just need to account for that. While this is the same thing as the multiplication algorithm, it allows you to avoid the need for BigInt libraries. Maybe, in a sense, it's the implementation of your own BigInt library, but isn't the point of Project Euler to teach you the relationships between math and coding? It seems a little disingenuous to say "I solved this by #include BigInt.h!" when really, one never actually looked at the math. – Emily Jul 24 '13 at 16:16
  • 1
    And yes, you can skip the prime factorization, but it gets quite very boring. – Emily Jul 24 '13 at 16:18
  • @Arkamis It is precisely the implementation of your own bigint library. And saying 'you just need to account for that' is precisely my point - unlike convolution where there's no 'pollution' of cross-terms, here you (eventually) have to take care of them, because while [0 14 0 4 5] and [1 4 0 4 5] may represent the same number, they are not the same representation - and, for instance, [9 11 0 2 6] and [1 0 0 0 2 6] do not have the same digit-sum. – Steven Stadnicki Jul 24 '13 at 16:19
  • @StevenStadnicki I never said take the digit sum of the un normalized convolution. – Emily Jul 24 '13 at 16:38
  • I think Steven's first question wasn't answered. The question once again is: If we are to implement the multiplication algorithm (either by convolution or any other), why is the integer factorization required? Can't we just simply multiply 23...100? Edit*: Ok I saw your answer. – Bibek Shrestha Aug 03 '14 at 18:12
  • @bibstha Arguably, the prime factorization reduces the total number of Cauchy products. Probably. For $n \le 100$, any term in the product $n!$ has at most one power of a two-digit prime as a factor. So the prime factorization of the products allows us to gather things up and compute very easily some powers of primes. Then we can convolve a rather small number of numbers, which might be more efficient. – Emily Aug 03 '14 at 20:06
  • PE's problem Factorial digit sum is just rated at 5% difficulty.... if 5% difficulty is expected someone to rewrite bigint, or playing with discrete convolution, then the expected knowledge slope is way too steep than my expectation :S – SKLTFZ May 23 '19 at 08:01
  • @Emily when I approach as you suggested I get 10! = 360271800, but it is not correct: (4x^4 + 3x^2 + 2x)*9x = 36x^5 + 0x^4 + 27x^3 + 18x^2 + 0x^1 + 0x^0 = 360271800 – Wasim Aftab Mar 23 '22 at 23:56
  • @Emily, Also, this is the output when I run MATLAB conv function: conv([4 0 3 2 0], [9 0]) = 36 0 27 18 0 0 – Wasim Aftab Mar 24 '22 at 00:05
0

I think that a way to add all the digits in hundred is add the even numbers then all the odd numbers. I tried this and it really worked out. Or another way is to keep on adding the number you started out with (small) and then taking a chart with all the numbers from 1 through 100 and ticking it of when you have reached the number or when you have came to this number. Example: 1,2,4.8,16,32,64. Thanks and I really wish that this helps you! Signing of, Srivacthi Nadar.

TonyK
  • 68,059
0

Interestingly, if you continue summing the digits for any integer factorial larger than or equal to 6, such that you end with a single digit, the answer will always be 9.

Reason is that any number divisible by 9, when written in decimal, has the property that its digit sum (when repeated until you have a single digit) is always 9.... and any factorial of any integer >= 6 includes 3*6 in the calculation, which is 18, which is divisible by 9.

Take the 27 solution you reached, gives 2+7 = 9

And Emily's answer of 40320, gives 4 + 3 + 2 = 9

Claud
  • 101
-1

Hint: One huge low-hanging fruit is that tons of those digits are going to be an enormous block of $0$'s at the front.

Use this fact to keep the magnitude of your answer under control as you compute.

rschwieb
  • 160,592
  • 1
    When you throw out the zeros, the remaining number is more than $120$ digits. – Lord Soth Jul 24 '13 at 17:11
  • not meaningful as log2(10^134) is still too large. – Grady Player Jul 24 '13 at 17:11
  • @GradyPlayer It is not a good idea to say "nonsense" to somebody who is trying to help you. – Lord Soth Jul 24 '13 at 17:12
  • @LordSoth, not my intention... and I apologize to all involved. – Grady Player Jul 24 '13 at 17:14
  • @LordSoth shrug I only remember that I solved that problem in Python in less than 5 minutes (coding time), and that was the first thing that occurred to me then. Guess I should go home and double check what I actually did :) – rschwieb Jul 24 '13 at 17:15
  • @rschwieb Agreed. I do not get why people are trying to get "huge insights" on this problem. The definition of this Project Euler is "mathematical/computer programming problems." Just write a code (it takes less than 1 hours in C) that can do arbitrary precision integer multiplication. – Lord Soth Jul 24 '13 at 17:17
  • 1
    @LordSoth Using insights, there are some Project Euler problems under 100 that can be done on a hand calculator within seconds. It's definitely worthwhile to look for the shortcuts before huge excursions into brute force... Not that I remember that this particular one has an insight that blew me away :) – rschwieb Jul 24 '13 at 17:19
  • @rschwieb Note that there is a reason behind why they ask $100!$ but not $10000000!$, as the former is manageable numerically. If you get such an insight that you can do $10000000!$ with a calculator, it will be a big breakthrough. – Lord Soth Jul 24 '13 at 17:22
  • Dear @LordSoth : It sounds like you are conflating some of my statements into a claim that doesn't exist. So far, I have just said that insights can greatly reduce computation load, and I have said that some problems are doable on a hand calculator. Judging from your last comment those two things have been merged in your head somehow into some claim about solving this problem. This is not the case. Hopefully this helps to straighten things out: thanks. – rschwieb Jul 24 '13 at 17:34
  • @rschwieb Can you point me in the direction of that insight? Maybe a keyword or two? – Emily Jul 24 '13 at 18:24
  • @rschwieb Sorry for any misunderstanding that I might have caused. My statement was intended to be general, and not directed to what you have said. What I meant was, "this may be one of those problems where no insight is necessary." – Lord Soth Jul 24 '13 at 18:29