Editorial for Baltic OI '13 P4 - Brunhilda's Birthday


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Let d(n) denote the number of calls Wotan needs to end the game when n children are left and let M={k1,,km} be the set of primes Wotan can choose from.

Dynamic Programming Solution

For 20 points it is enough to evaluate the obvious formula

d(n)=1+minkMd(n(nmodk))

using dynamic programming. Then all queries can be answered by simple lookup. To handle the case d(n)= suffices to check whether

nlcm(k1,,km)=kMk

(since if n is not divisible by k after calling k less children will be over, but if n is at least the product p of all numbers Wotan can call, after any call at least p children will remain) or to simply set d(n)=1 for n0 before evaluating the above formula. Runtime is Θ(mn+Q) in both cases.

Greedy Approach

Let us denote the predecessor, i.e. the number of children that are left after Wotan made a perfect call, of n as π(n). If there are multiple solutions, let π(n) be the minimum of these numbers. The main point of the solution is the following

Proposition 1. Wotan can call the numbers greedily, i.e. π(n)=minkM(n(nmodk)). This fact is—once stated—quite obvious, but it can be established rigorously using the following

Lemma 2. π and d are both monotonically increasing in n.

Proof. We show this for any interval [0N] by induction on N. Without loss of generality let us assume that d(N)<1. The case N=0 is trivial. Otherwise we have π(N)N1 as stated above and thus π(N)=minkM(N(Nmodk)). Since (N1)modk(Nmodk)1 for any N, k we have π(N)π(N1). Thus

d(N)=d(π(N))+1d(π(N1))+1d(N1)

because of the monotonicity of d in [0π(N)][0N1].

To show that this suffices for subtask 2 we need to establish an upper bound for d(n). For simplicity let kmax denote maxM.

Lemma 3. Let n=nkmax and d(n)<1. Then d(n)2n.

Proof. We use induction on n. Again there is nothing to show for n=0. For n1 we have π(n)<n by assumption and thus

π(π(n))π(n1)(n1)((n1)modkmax)=(n1)(kmax1)=nkmax=(n1)kmax

by monotonicity of π. Using the monotonicity of d we get thus d(n)=d(π(π(n)))+2d((n1)kmax)+2=2(n1)+2=2n.

Once again using monotonicity we get

Corollary 4. If d(n)<1, then d(n)2nkmax. Especially we have d(n)=O(nm).

Using the prime number theorem stating that the nth prime is asymptotically as big as nlnn one can decrease this bound further to O(nmlogm), however, this is not required directly for the solution.

Since we can calculate π(n) primitively in O(m) we can answer one query in O(m+n) time. This suffices for subtasks 1 and 2.

DP Over Inverse Function

Let d(1) denote the inverse function of d, i.e.

d(1)(k)=max{n:d(n)k}.

Since π(k+kmax)>k and thus d(k+kmax)>d(k), we have

d(1)(k+1)>d(1)(k)+kmax

Thus having calculated d(1)(x) for x[1k] one can calculate d(1)(k+1) using binary search in the interval [d(1)(k),d(1)(k)+kmax]. It further suffices to check for given x in this interval whether π(x)>d(1)(k) (instead of really calculating d(x), which would be too slow). So one can calculate this function for every needed value of k in time O(n+m) (here the additional log-factor mentioned before comes in handy).

With this function one can answer any query in logarithmic time using binary search or simply fill an array d[1n] of all values in time O(n) and then answer queries in O(1). Both suffices to get full score.

Model Solution: Fast Evaluation of the Predecessor Function

Instead of minimizing π(n) we can simply maximize the term we subtract (since n is fixed), let's call it μ(n,k)=nmodk. If we plot some of those functions for variable n and some kM the image consists of a set of straight lines of slope 1 and "breaks".

Thus for μ(n):=maxkMμ(n,k) we get the same simple characteristic. If we plot all those functions — both μ and μ — and scan through this image from right to left the optimal k can only change when a break occurs. Thus if we evaluate μ at all those breaks of all the μ-functions we can simply fill in the rest of them by subtracting one from the next one at the right.

For any breakpoint n, we have that μ(n1) is k1 for some kM. Thus to initialize our array M[1n] of values of μ it suffices to set M[ak1]=k1 for any a and increasing kM. This needs

kmnk=nkm1kni=1m1k=nHm=O(nlogm)

steps (messing with analytic number theory one can reduce this bound further to O(nloglogm) but with really good constant factor.

Afterwards one can calculate π(n) on the fly in constant time and thus use the simple DP approach from the beginning to get full score.

An implementation using a priority queue to evaluate μ using the same ideas above is expected to get something around full score, too, depending on the data structure used.


Comments

There are no comments at the moment.