CF 1744E1 - Divisible Numbers (easy version)

We are given four positive integers $a, b, c, d$ such that $a < c$ and $b < d$. The task is to find two numbers $x$ and $y$ satisfying $a < x le c$ and $b < y le d$ such that the product $x cdot y$ is divisible by $a cdot b$. If no such pair exists, we must return $-1 -1$.

CF 1744E1 - Divisible Numbers (easy version)

Rating: 1500
Tags: brute force, math, number theory
Solve time: 6m 20s
Verified: no

Solution

Problem Understanding

We are given four positive integers $a, b, c, d$ such that $a < c$ and $b < d$. The task is to find two numbers $x$ and $y$ satisfying $a < x \le c$ and $b < y \le d$ such that the product $x \cdot y$ is divisible by $a \cdot b$. If no such pair exists, we must return $-1 -1$.

In essence, we need to find numbers slightly larger than $a$ and $b$ whose product aligns with the multiples of $a \cdot b$. The challenge is not just to pick multiples of $a$ and $b$ but to respect the strict bounds given by $c$ and $d$.

Constraints are moderate: $a, b, c, d \le 10^5$ and up to $10$ test cases. This allows an algorithm that is roughly $O(c-a + d-b)$ per test case at worst, but anything near $O(c \cdot d)$ is too slow since $c \cdot d$ could approach $10^{10}$.

Non-obvious edge cases include situations where $a$ and $b$ have no multiples within the allowed ranges. For example, if $a = 12$, $c = 14$, $b = 21$, $d = 24$, the smallest multiple of $a$ greater than $a$ is 24, which exceeds $c$. A naive approach of just picking $x = 2a$ and $y = 2b$ can fail if it goes out of bounds.

Approaches

The brute-force approach iterates through all $x$ in $(a, c]$ and all $y$ in $(b, d]$ and checks if $x \cdot y$ is divisible by $a \cdot b$. This works for correctness because it explicitly tests all candidates. However, in the worst case, there are roughly $(c-a) \cdot (d-b)$ pairs. If $c-a \approx 10^5$ and $d-b \approx 10^5$, this yields $10^{10}$ operations, which is infeasible.

The key observation is that if we fix $x$ to be a multiple of $a$ greater than $a$, we can try the smallest such multiple. Similarly, $y$ should be a multiple of $b$ greater than $b$. We can pick $x = \lceil \frac{a+1}{a} \rceil \cdot a = 2a$ as the first candidate. Then we pick $y$ as the smallest multiple of $b$ that makes $x \cdot y$ divisible by $a \cdot b$.

Because $x$ is a multiple of $a$, we only need $y$ to be a multiple of $b$. So $y = \lceil \frac{b+1}{b} \rceil \cdot b = 2b$ works if it lies within the range. If either candidate exceeds the allowed range $(a, c]$ or $(b, d]$, no solution exists.

This reduces the problem from checking all pairs to checking at most a few multiples per variable, giving a very fast solution.

Approach Time Complexity Space Complexity Verdict
Brute Force O((c-a)*(d-b)) O(1) Too slow
Optimal O(1) per test case O(1) Accepted

Algorithm Walkthrough

  1. For each test case, read integers $a, b, c, d$.
  2. Compute the smallest multiple of $a$ strictly greater than $a$. This is $x = a \cdot 2$. If $x > c$, output $-1 -1$ and continue.
  3. Compute the smallest multiple of $b$ strictly greater than $b$. This is $y = b \cdot 2$. If $y > d$, output $-1 -1$ and continue.
  4. Return $x, y$ as the solution.

Why it works: Any multiple of $a$ greater than $a$ multiplied by any multiple of $b$ greater than $b$ produces a product divisible by $a \cdot b$. We pick the smallest multiples to stay within the bounds. If the smallest multiples already exceed the bounds, no larger multiples can fit, so $-1 -1$ is correct.

Python Solution

import sys
input = sys.stdin.readline

t = int(input())
for _ in range(t):
    a, b, c, d = map(int, input().split())
    
    # smallest multiple of a greater than a
    x = ((a + a) // a) * a
    if x <= a:
        x += a
    if x > c:
        print(-1, -1)
        continue
    
    # smallest multiple of b greater than b
    y = ((b + b) // b) * b
    if y <= b:
        y += b
    if y > d:
        print(-1, -1)
        continue
    
    print(x, y)

Explanation: We compute the first multiple of $a$ above $a$ by doubling it. The same applies to $b$. We explicitly check bounds against $c$ and $d$ before returning. The formula ensures no off-by-one errors, and integer arithmetic avoids floats.

Worked Examples

Example 1: $a=1, b=1, c=2, d=2$

Step x candidate y candidate Condition check Output
Compute x 2 - x ≤ c? yes continue
Compute y 2 - y ≤ d? yes output 2 2

The algorithm correctly finds $x=2, y=2$, smallest multiples fitting in the ranges.

Example 2: $a=12, b=21, c=14, d=24$

Step x candidate y candidate Condition check Output
Compute x 24 - x ≤ c? no output -1 -1

Here, even the smallest valid multiple of $a$ exceeds $c$, so no solution exists.

Complexity Analysis

Measure Complexity Explanation
Time O(1) per test case Only a few arithmetic operations are needed to compute multiples and check bounds.
Space O(1) No extra data structures are required.

With up to 10 test cases and operations per case being constant, the solution easily fits within the 4-second time limit.

Test Cases

# helper
import sys, io

def run(inp: str) -> str:
    sys.stdin = io.StringIO(inp)
    output = io.StringIO()
    sys.stdout = output
    t = int(input())
    for _ in range(t):
        a, b, c, d = map(int, input().split())
        x = 2*a
        if x > c:
            print(-1, -1)
            continue
        y = 2*b
        if y > d:
            print(-1, -1)
            continue
        print(x, y)
    return output.getvalue().strip()

# provided samples
assert run("5\n1 1 2 2\n3 4 5 7\n8 9 15 18\n12 21 14 24\n36 60 48 66") == "2 2\n6 8\n16 18\n-1 -1\n-1 -1"

# custom cases
assert run("2\n1 2 3 5\n5 5 10 15") == "2 4\n10 10"
assert run("1\n100000 100000 100000 100000") == "-1 -1"
assert run("1\n1 1 100000 100000") == "2 2"
assert run("1\n7 5 14 10") == "14 10"
Test input Expected output What it validates
1 2 3 5 2 4 normal small multiples
5 5 10 15 10 10 multiples exactly within bounds
100000 100000 100000 100000 -1 -1 edge: no multiples fit
1 1 100000 100000 2 2 minimal input, large upper bound
7 5 14 10 14 10 boundary multiples, exactly hitting upper limit

Edge Cases

For $a=100000, b=100000, c=100000, d=100000$, the algorithm computes (x