Problem 5 - Pairing Cards

We will discuss the solution to Pairing Cards from AIO 2025.

Solution

Subtask 1: S = 0 and N ≤ 1000

Since S = 0 and Ai ≥ 1 for all i, it is impossible for any pair to add to S in this subtask. All pairs must have a difference of D.

A card with a value of Ai could be paired with a value of either Ai - D or Ai + D and it's not clear which one we should choose. But if we instead look at the card with the smallest value (A1) there is only one option to pair it with: A1 + D (we can ignore A1 - D because it has a smaller value which contradicts the fact that A1 has the smallest value). If there is no card with value A1 + D then we can output NO and stop our program. Otherwise, we pair A1 with A1 + D, remove these two cards, and repeat this process using the new smallest card.

Below is my code in Python and C++ for this subtask. I suggest trying to code the solution yourself and only look at our code after you finish or if you get stuck. Make sure your code works when D = 0 because this case can be tricky!

import sys

# N is the number of cards.
N = 0
# D and S are the allowed difference and sum of paired cards.
D = 0
S = 0

# A contains the values on the cards. Note that the list starts from 0, and so
# the values are A[0] to A[N-1].
A = []

# Read the values of N, D, S, and the values on the cards.
N, D, S = map(int, input().strip().split())
A = list(map(int, input().strip().split()))

while len(A) > 0:
  # pair A[0] with A[0]+D
  value = A[0]
  A.remove(value)
  if value+D not in A:
    print("NO")
    sys.exit(0) # this ends the program
  else:
    # A[0]+D from the list
    A.remove(value+D)
    
print("YES")
#include <cstdio>
#include <vector> // for std::vector
#include <algorithm> // for std::find

/* N is the number of cards. */
int N;
/* D and S are the allowed difference and sum of paired cards. */
int D;
int S;

std::vector<int> A;

int main(void) {
  /* Read the values of N, D, S, and the values on the cards. */
  scanf("%d%d%d", &N, &D, &S);
  for (int i = 0; i < N; i++) {
    int a;
    scanf("%d", &a);
    A.push_back(a);    
  }

  while (!A.empty()) {
    int value = A[0];
    A.erase(A.begin());
    auto it = std::find(A.begin(), A.end(), value+D);
    if (it == A.end()) {
      printf("NO\n");
      return 0;
    } else {
      A.erase(it);
    }
  }

  printf("YES\n");
}

Subtask 2: D = 0 and N ≤ 1000

In this subtask we can either pair equal values or values that add to S.

Assume for now that all values are distinct and so our only option is to pair values that add to S. In this case we don't need to make any pairing decisions: for each value Ai our only option is to pair it with a card of value S - Ai. This allows us to use code similar to subtask 1: we continuously try pairing cards until either we can't (so we print NO) or all the cards are paired (so we print YES).

When the values are not all distinct then we need to make a choice. For example, if there are two cards with value Ai = x we need to choose whether to pair them together or to pair them both with cards of value S - x. The first option (pair them together) is always optimal — try to prove it yourself and then read my proof.

Proof

We will use a type of proof called an exchange argument. In this proof style, we start with a solution that does not meet the criteria of our observation and we prove that we can change it so that it does meet our criteria.

Assume we did not pair the two cards together. Then, we paired the two cards of value x with two cards of value S - x. However, we could swap the pairs around so that the two x's are paired together and the two S - x's are also paired together.

Our solution is: first pair cards of equal value until no such pairs remain. Then, all remaining cards have distinct values and we can use the method described above.

Subtask 3 and Full Solution

In these subtasks each card has three options for what it could be paired with:

If we consider the smallest card (A1) then similarly to subtask 1 we remove one of the options (A1 - D) and so only two options remain: A1 + D and S - A1. If there are no cards with either of these values then it is impossible and we can print NO. If only one of these options appears on a card then we must do that pairing. Otherwise we can assume that there are cards with both values A1 + D and S - A1. We can greedily decide which one to pair A1 with: We can repetitively apply this process until either a pairing is impossible or all cards are paired.

Depending on the time complexity of your solution it will pass either subtasks 1-3 or the full problem.

Two examples of this algorithm are shown below.

Click here to go back.