Loading [MathJax]/jax/output/HTML-CSS/jax.js

Sunday, October 13, 2013

TopCoder SRM 591 Editorial: PyramidSequences

PyramidSequences

First, fix some n and m. We begin by looking at an easier problem: If instead of looking at sequences of the form 1,2,,n1,n,n1,,3,2, what if all the sequence elements were distinct (e.g. if the sequence was of the form 1,2,,2n2)? The Chinese remainder theorem guarantees that a number x from the n-sequence will be paired with a number y from the m-sequence if and only if xy(mod2g), where g=gcd(n1,m1). We can partition the n- and m-sequences into equivalence classes modulo 2g; each class contains (n1)/g or (m1)/g elements, so there are (n1)(m1)/g2 pairings per class, or (n1)(m1)/g2, or 2(n1)(m1)/g unique pairings.

Unfortunately, the pairings are not unique. Each k in the n-sequence has two possible indices modulo 2g: {k%(2g) and (2nk)%(2g)}. Let us first consider the two indices are equal, i.e. k(2nk)(mod2g). Simplifying, this gives us kn(modg). Since g is a multiple of n1, then n1(modg), so our final expression is k1(modg); i.e. k1 or g+1(mod2g). Note that this condition is independent of n or m, so it suffices to simply find the number of k equivalent to 1 or g+1 modulo 2g in each sequence and multiply the counts accordingly.

Now consider the case in which k has two distinct indices, k%(2g) and (2nk)%(2g). Again, since n1(modg), the second index can be written (2k)%(2g). If k%(2g)[2,g], then (2k)%(2g)[g+2,2g] and vice versa. Thus, each k appears exactly once in the range [2,g] and exactly once in [g+2,2g]. It suffices, then, to compute the result for one range. This is simply (g1)(n1)(m1)/g2.

Putting the two cases (k1(modg) or not) together, we have the following Python code. Some care must be taken to account for the special cases 1, n, and m.

from fractions import *

class PyramidSequences(object):
 def distinctPairs(self, n, m):
  g = gcd(n - 1, m - 1)
  an, am = [(x - 1) / g for x in n, m]
  bn, bm = [x / 2 + 1 for x in [an, am]]
  cn, cm = [x / 2 + (x % 2) for x in [an, am]]
  return (g - 1) * an * am + bn * bm + cn * cm

No comments:

Post a Comment