How many 16-digit integers are there such that the sum of the square of their digits is a square?
Examples And Test Cases
2 2 8 3 is a 4 -digit integer such that the sum of the square of its digits is a square. 2 2 + 2 2 + 8 2 + 3 2 = 8 1 = 9 2 .
There are 3 3 2 4 -digit integers with the required property.
This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try
refreshing the page, (b) enabling javascript if it is disabled on your browser and,
finally, (c)
loading the
non-javascript version of this page
. We're sorry about the hassle.
Dynamic programming solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
A bit of dynamic programming is convenient here. I keep track of a table t [ d , k ] = how many numbers with d digits have digit-square-sum of k , and generate the table by increasing d : t [ d + 1 , k ] = a = 0 ∑ 9 t [ d , k − a 2 ] . (For the first digit we start at a = 1 instead: a number does not start with zero.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Output:
215576406208883
This one is mostly straightforward, with a couple of tricky aspects. The first thing to see is that just "brute force" checking every possible 16-digit base-10 integer for the property isn't just inelegant, it's probably impractical unless you have a supercomputer handy. Instead, we take advantage of the fact that each sequence of digits is repeated many times, (e.g. 4413, 1344 and 4314 give equivalent answers). So, the abstract algorithm goes something like this:
Loop over all unique sequences of n-digits:
check condition
if condition satisfied:
matches += number of permutations for sequence
Finding the unique digit sequences is easy to implement recursively (see below). There is one wrinkle that needs to be handled carefully: only numbers starting with non-zero digits count as n-digit numbers (i.e. 4430 counts as 4-digit number, but 0443 doesn't). This means that you need to apply the binomial theory a bit differently when accounting for the number of places that zeros can appear in a given sequence. Here is a bit of pseudocode with an algorithm for computing the number of permutations:
n = # of digits remaining in sequence
zc = number of zeros in sequence
permutations = (n-1)! / [(zc!)(n-1-zc)!] # binomial coefficient (Note that 0!=1.)
n -= zc
Loop over digits from 1 to 9:
c = number of times digit i appears in sequence
permutations *= n! / [c!(n-c)!] # binomial coefficient (Note that 0!=1.)
n -= c
Ok, here's the python code I used to get the answer. One detail is that, when searching for unique digit sequences, I go backwards from 9 to zero to simplify the aforementioned issues with counting zeroes properly. Also, I do the outermost loop separately, and loop from 9 down to 1 (not zero) for the same reason. Finally, note the semantics for making copies of the digit repetition pattern list within the recursive algorithm are a bit subtle.
import math
def is_sq(n): # returns true if a digit is a square
return int(math.sqrt(n) + 0.5) ** 2 == n
def degen(patt): # returns degeneracy of digit pattern patt - list of digit repetitions
n= sum(patt)
zc = patt[0] # Note: first element of patt must contain # of zeroes
perms = fac(n-1) // fac(zc) // fac(n-1-zc) # binomial coeff
n -= zc
for i in patt[1:]: # loop over remaining elements of patt
perms *= fac(n) // fac(i) // fac(n-i)
n -= i
return perms
def count_sq(n, i, patt, tot): # recursive function to identify unique digit sequences
# and keep running tally of numbers matching condition that sum
# of squares of all digits is also a perfect square
# n: number of digits remaining to be found
# i: index of current digit value
# patt: ordered list of repetition counts for digits 0-9
# tot: sum of squares of digits found so far
if n<1 or !(i in range(10)) or tot <0 or len(patt)!=10:
# check partial list of possible failure conditions
print "Error: at least one parameter out of acceptable range"
print n, i, patt, val
exit(1)
cnt = 0 # total number of matches found, up to an including current recursion level
for j in range(i, -1, -1): # reverse loop over remaining possible digits from i down to 0
pattcpy = patt[:] # create local copy of digit pattern to modify
pattcpy[j]+=1 # increment pattern count for current digit
if n>1: # if at bottom recursion level
cnt += count_sq(n-1, j pattcpy[:], tot+j*j) # make recursive call for next level
else:
if is_sq(tot+j*j): # if sum of squares of digits matches condition
cnt += degen(pattcpy[:]) # increment count by degeneracy of pattern
return cnt
# main body
initpatt = [0,0,0,0,0,0,0,0,0] # initialize ordered list of digit repetitions
cnt_4_dig=cnt_16_dig=0 # accumulator variables for demonstration
for i in range (9,0,-1): # outer loop for leading digit; reverse order simplifies counting of zeroes
patt = initpatt[:] # create local copy of initial digit pattern
patt[k] += 1 # increment count for current digit
cnt_4_dig += count_sq(3, k, patt[:], k*k)
cnt_16_dig += count_sq(15, k, patt[:], k*k)
print cnt_4_dig # outputs 332
print cnt_16_dig # outputs 215576406208883
Problem Loading...
Note Loading...
Set Loading...
A simple memoization solution does the trick handily. We note that there will be a state (current sum, numbers remaining), and that since the maximum number is 8 1 ∗ 1 6 = 1 2 9 6 , and we can have at most 16 numbers, there are about 20,000 states, easily doable. Sample C++ code below, noting the use of a for loop over all starting digits to avoid numbers with leading zeros