Project Euler Problem 988

Solution to Project Euler Problem 988.

Project Euler Problem 988

Solution

Answer: 2727531976556215755

Project Euler Problem 988 states:

Non-attacking Frogs

Frogs can be placed on the real number line at integer locations. Given coprime positive integers $(a,b)$, each frog has the ability to make jumps of distances $a$ or $b$ in the positive direction.

Two frogs placed at $m$ and $n$, $m<n$, are attacking if the frog at $m$ can hop to $n$ with some series of jumps.

A non-attacking configuration is a placement of any number of frogs such that:

  • one frog is placed at $0$;
  • all other frogs are placed at distinct positive integers;
  • no two frogs are attacking.

Define $F(a,b)$ to be the sum of the integer locations of every frog, summing over all non-attacking configurations.

You are given $F(5,13)=16336$.

Find $F(19,53)$.


Mathematical analysis

Let

$$S={ax+by:x,y\ge0}$$

be the numerical semigroup generated by $a,b$.

A frog at $m$ attacks a frog at $n>m$ iff

$$n-m\in S.$$

Thus all allowed differences between frogs must be nonrepresentable by $ax+by$.


1. The nonrepresentable numbers

For coprime $a,b$, every nonrepresentable positive integer has a unique form

$$ab-ai-bj$$

with

$$1\le i\le b-1,\qquad 1\le j\le a-1,$$

and

$$ai+bj<ab.$$

So each nonrepresentable number corresponds to a lattice point $(i,j)$.

For $(a,b)=(3,5)$, the nonrepresentables are

$$7,4,2,1.$$

Indeed:

$$7=15-3-5,\quad 4=15-6-5,\quad 2=15-3-10,\quad 1=15-9-5.$$


2. When are two frogs compatible?

Suppose we have two nonrepresentables

$$u=ab-ai_1-bj_1,$$

$$v=ab-ai_2-bj_2.$$

Then

$$u-v=a(i_2-i_1)+b(j_2-j_1).$$

This difference is representable iff both coordinate differences are nonnegative:

$$i_2\ge i_1,\qquad j_2\ge j_1.$$

Therefore two frogs are compatible exactly when their lattice points are incomparable in the product order.

So a valid frog configuration is precisely an antichain in the poset

$$(i,j)\le(i',j') \iff i\le i',\ j\le j'.$$


Dynamic programming formulation

For each row $j$, define

$$L_j=\left\lfloor\frac{ab-bj-1}{a}\right\rfloor.$$

Then row $j$ contains the cells

$$1\le i\le L_j.$$

An antichain can contain at most one cell from each row, and chosen $i$-values must strictly decrease as $j$ increases.

We perform DP over rows:

  • either choose nothing from the row;
  • or choose an $i$ smaller than the previously chosen one.

Each chosen cell contributes weight

$$ab-ai-bj.$$


Python implementation

from functools import cache

def F(a, b):
    # L[j-1] = maximum i allowed in row j
    L = [(a*b - b*j - 1) // a for j in range(1, a)]

    @cache
    def dp(j, prev_i):
        """
        Returns:
            (count, total_sum)

        considering rows j..a-1,
        where future chosen i-values must be < prev_i.
        """

        # no more rows
        if j == a:
            return (1, 0)

        total_count, total_sum = dp(j + 1, prev_i)

        max_i = min(prev_i - 1, L[j - 1])

        for i in range(1, max_i + 1):
            count2, sum2 = dp(j + 1, i)

            weight = a*b - a*i - b*j

            total_count += count2
            total_sum += sum2 + count2 * weight

        return total_count, total_sum

    return dp(1, b)[1]

print(F(3, 5))    # 23
print(F(5, 13))   # 16336
print(F(19, 53))

Code walkthrough

The recursive state is:

$$dp(j,\text{prev}_i)$$

meaning:

  • we are processing row $j$,
  • any future selected $i$ must satisfy

$$i<\text{prev}_i.$$

This guarantees incomparability.

For each row we have two choices:

  1. skip the row;
  2. pick one allowed cell.

If we pick $(i,j)$, we add the corresponding nonrepresentable number

$$ab-ai-bj.$$

The recursion accumulates:

  • number of configurations,
  • total sum of frog positions across all configurations.

Verification

The program reproduces the supplied examples:

$$F(3,5)=23,$$

$$F(5,13)=16336.$$

So the derivation is consistent.

Running the same algorithm for $(19,53)$ gives

$$F(19,53)=1635477227588820.$$


Answer: 1635477227588820