views:

235

answers:

3

I've recently joined TopCoder and have been practicing in the Practice Rooms for the last few days. I came across this problem which I cant seem to solve. Any help will be appreciated.

The problem

The product value of a string is the product of all the digits ('0'-'9') in the string. For example, the product value of "123" is 1 * 2 * 3 = 6. A string is called colorful if it contains only digits and the product value of each of its nonempty contiguous substrings is distinct.

For example, the string "263" has six substrings: "2", "6", "3", "26", "63" and "263". The product values of these substrings are: 2, 6, 3, 2 * 6 = 12, 6 * 3 = 18 and 2 * 6 * 3 = 36, respectively. Since all six product values are distinct, "263" is colorful.

On the other hand, "236" is not colorful because two of its substrings, "6" and "23", have the same product value (6 = 2 * 3).

Return the k-th (1-based) lexicographically smallest colorful string of length n. If there are less than k colorful strings of length n, return an empty string instead.

My approach

We can't have '0' and '1' as digits in n. All digits must be distinct. So to begin with, n should be smaller than 9. (only the digits 2, 3, 4, 5, 6, 7, 8, 9 can be used, each of them only once).

Since we know that, we can start with "23" (the smallest 2-digit colorful string) as the base string and add one of the allowed digits (check if the string is still colorful or not, on each addition) until we reach length n.

Once we reach length n, we can "play around" with the digits to find the k-smallest.

My question

I feel like this approach will not be fast enough. Even if it is, in what systematic way should I play around with the digits, so that I start from the smallest and make my way through the kth-smallest?

How can I make progress on this problem with this approach? Or are there smarter ways to follow in these kind of problems?

I'm not asking for any solutions or anything. I'm just asking for some clues and some lead.

Some problems I solve in seconds, some take hours of thinking and some like this I can't do it. But I believe all it takes is some practice, but I cannot make progress without someone leading the way.

Thanks in advance =)

*by the way, this question is from SRM 464 DIV 2 - 500pt. problem. All copyright goes to TopCoder.

+2  A: 

I feel like this approach will not be fast enough.

Why not? I wouldn't even bother being "smart" about it: You have 8 digits, each of which can be used at most once. This has a total count of 8*7 + 8*7*6 + 8*7*6*5 + ... 8*7*6*5*4*3*2*1 = 109592, which is quick for a computer to run through.

Enumerate all of these in lexicographical order, and check each one to see if it's "colorful" or not.

Jason S
Yes, I guess you're right. When I first read the problem, I tried to think of a non-exhausting way, thinking that brute-force would take a lot of time.But still, to do this in a "smarter" way, without generating all possibilities, what can be done?
Murat
Except that the 7! etc. terms are wrong. A two-digit number, for example, will have 8 x 7 = 56 possible combinations, not 2! = 2. You're looking at 8!/0! + 8!/1! + 8!/2! + ... + 8!/6! possibilities. Of course, this is still small enough to enumerate in 32-bit integers on any halfway modern computer.
David Thornley
@David -- right. I meant combinations not permutations... er, it's not combinations either since the ordering counts. Anyway, fixed.
Jason S
I just realized that this takes a little longer than mentioned. Because checking for colorfulness takes 2^n time.(8!/0!)*2^8 + (8!/1!)*2^7 + .... > 10321920 which maybe a lot?
Murat
@Jason Follow-up question: Now we're working in hexadecimal, or sexagesimal and want to find colorful numbers. That's why it's interesting to think of an algorithm for this that is better than just brute force. :)
Tyler McHenry
@Murat - I'm pretty sure you can check for colorfulness in `O(n)`, and very sure you can do it in `O(n^2)`. You don't need `O(2^n)`.
IVlad
@IVlad: Since the set of possible colorful numbers is bounded (see above), and the length is bounded, all operations are O(1) technically. Aside from that, I don't see how to check in O(n), given that there are `n(n+1)/2` or O(n^2) substrings, and since we're looking for equalities it appears to me we'd have to check all of them.
David Thornley
Although there are O(n^2) substrings, if we enumerate all colourful numbers in order then only O(n) substrings will be the different from one number to the next, so O(n) time is possible.
j_random_hacker
+2  A: 

One way to reduce the search space is to consider this: A string of length n can be colorful only if the substring given by its first n-1 characters is also colorful. That this assertion is true should be fairly obvious.

Suppose you have a function colorful(n) which returns the set of all colorful strings of length n. You could implement it recursively, like this:

colorful(n):
  if n = 1:
    return { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }

  def colorful_subs = colorful(n-1)
  def colorfuls

  for each sub in colorful_subs:
    remaining_digits = { 2, 3, 4, 5, 6, 7, 8, 9 } - digits_in(sub)

    for each digit in remaining_digits:
      if is_colorful(sub, digit):
        colorfuls += (sub + digit)

  return colorfuls

And the supporting function is_colorful can take advantage of the fact that the substring given as the first argument is already known to be colorful and to not contain the appended digit.

Then call colorful(n) and select the kth element of the returned set. (note that we do have to include "0" and "1" in the base case, otherwise it would give the wrong answer for n=1)

This is basically a dynamic programming approach. I'm sure this could be improved -- there might be a clever way to figure out if appending a certain digit to a colorful number would make the number no longer colorful without actually doing it and checking. But this certainly does check considerably fewer numbers than all of the possible permutations of 2-9.

Tyler McHenry
+1. I think you are not allowed to append a digit that is the product of two preceding digits. Otherwise you'll have two equal products. For example: `324` => we can't append `8`, because `8 = 2*4`. We can append everything else. We only need to look two digits behind because the product of any three distinct digits `> 1` is `> 10`.
IVlad
Thanks for the answer, that helps. One last thing, how do I check for colorfulness in O(N) time?
Murat
Looks like you're missing a "4" in your `remaining_digits`. (I know, what an utterly pointless nitpick... :) )
j_random_hacker
+2  A: 

Topcoder has a forum in which they create a thread for each SRM (464 is here). Maybe your question is already answered there :)

kunigami
Here's the editorial for the match, which has a brief explanation of the solution: http://www.topcoder.com/wiki/display/tc/SRM+464
Tom Sirgedas
thank you kunigami and tom! solved.
Murat