A few thoughts, no definite answer yet.
First, your approach is quite reasonable imo. You have numbers up to 10^9, which you cannot preprocess all. Instead, you take into account that the smaller numbers "somehow" are picked more often by the process, and so you memoize only up to a certain upper boundary, here 10^7.
An easy improvement in your basic algorithm is by realizing that you need to memoize only multiples of 2
or 3
. All other inputs can easily be related to those numbers in the count
function.
Another optimization could be to vary the upper bound 10^7 empirically. That is, choose some values between, say, 10^5 and 10^8 and then hand in the one with the minimum execution time.
Improving this basic approach is not trivial, but the way to improve it is by getting insight into the number selection procedure. Basically, one should memoize those numbers which are selected more often, and leave those numbers out which are picked only few times.
One could do a lot here, but usually the required results on which the memoization procedure is based have to be generated on-the-fly in the program which you hand in to the contest. I guess this makes it hard to come up with competitive solutions. I could imagine that simple rules of the form "memoize all below 10.000"
, "memoize multiples of 5 above 10.000"
, "memoize multiples of 7 above 10.000"
and so on could be useful. Such rules can be easily encoded into the program without requiring too much memory. They could be found in advance by genetic algorithms, for example.
For an exact approach, one can assume a uniform distribution of the coin numbers in the problem. Then one can loop over all numbers i
up to 10^9 and aquire how often each number k<i
is chosen by the procedure. The result is an array count[i]
. Next you pick a lower boundary L
for count[i]
and memoize all numbers i
where count[i]>=L
. However, as mentioned, this procedure is too costly as it has to be done in the run itself.
What you could do instead is to pick only, say, the N
most-often picked numbers, and hard-code them in the code. The actual number N
of included memoizaion numbers can be determined by the memory constraint in the task.