CF 1266B - Dice Tower

The problem asks us to figure out whether it is possible to build a vertical tower of standard six-sided dice such that the sum of all visible pips equals a given integer. We have an unlimited number of dice, and for each die, we can choose its orientation.

CF 1266B - Dice Tower

Rating: 1000
Tags: constructive algorithms, math
Solve time: 2m 2s
Verified: yes

Solution

Problem Understanding

The problem asks us to figure out whether it is possible to build a vertical tower of standard six-sided dice such that the sum of all visible pips equals a given integer. We have an unlimited number of dice, and for each die, we can choose its orientation. Only the top face of the top die and all side faces of all dice except the bottom-facing faces count toward the sum. Essentially, for a single die we see five faces: four sides and the top, while the bottom face is hidden.

The input consists of t integers, each representing a target sum of visible pips. For each target, we must print YES if there exists a tower configuration that produces exactly that sum, or NO if it is impossible.

The constraints are tight in a way that forbids naive enumeration. The number of target sums t can go up to 1000, and the target sums themselves can be as large as $10^{18}$. This immediately rules out any algorithm that tries to simulate all towers or even iterate over all possible tower heights, since the height required could exceed practical computation limits. Instead, we need a solution that works mathematically without iterating through every tower configuration.

A subtle edge case arises from the smallest towers. For instance, if the target sum is smaller than the minimum number of pips visible on a single die (which is 1 on top plus at least 4 on sides minus overlaps), a naive approach might incorrectly assume no configuration exists, but careful orientation might still reach the target. Similarly, for very large sums, a careless implementation that does not account for arithmetic patterns of dice totals might incorrectly reject a feasible solution.

Approaches

The brute-force approach would attempt to build all possible towers up to a height where the sum of visible pips could reach the target. For each die added, we could consider all four possible side orientations and six top faces, then sum the visible pips. This approach is correct in principle because it explores all configurations, but it fails quickly: even if we consider only side faces, the number of iterations grows linearly with the target divided by the average pips per die, which could be on the order of $10^{18}$. This is entirely impractical.

The key insight comes from observing the pattern of visible pips. Each die contributes either 14 or 20 pips to the sum, depending on whether it is a middle die or the top die. If we focus on maximizing side sums, a middle die contributes the sum of four sides (14) and the top die adds its top (1-6) plus four sides (14), giving totals from 15 to 20 for the top die. This transforms the problem into a simple check: can we express the target sum as 14 times some number of middle dice plus 15-20 for the top die?

With this observation, the solution becomes a combination of modular arithmetic and bounds checking: for each target, we compute how many middle dice would be required if the top die contributes a given value, then verify if a non-negative integer solution exists. This reduces the problem from simulating dice towers to a small finite check per target.

Approach Time Complexity Space Complexity Verdict
Brute Force O(target / 1) ~ O(10^18) O(1) Too slow
Optimal O(1) per query O(1) Accepted

Algorithm Walkthrough

  1. For each target sum x, check if it is at least 15. The minimum sum for a single die is 15 (top face 1 plus four sides 14) because the bottom face is hidden.
  2. If x is less than 15, immediately output NO.
  3. Otherwise, subtract multiples of 14 from x until the remainder is between 15 and 20 inclusive. Each subtraction corresponds to adding a middle die, which contributes exactly 14 visible pips.
  4. If the remainder falls in the range 15-20, output YES. Otherwise, output NO. This remainder represents the top die, which can be oriented to achieve any visible pip sum in that range.
  5. Repeat the process for all t queries.

Why it works: Each middle die contributes exactly 14 pips to the visible sum. By using as many middle dice as needed, any target sum beyond 14 can be reduced to a remainder that a top die can achieve (15-20). No sum outside this range is reachable, so checking this remainder guarantees correctness.

Python Solution

import sys
input = sys.stdin.readline

def solve():
    t = int(input())
    targets = list(map(int, input().split()))
    
    results = []
    for x in targets:
        if x < 15:
            results.append("NO")
            continue
        
        remainder = x
        # Reduce remainder by multiples of 14
        while remainder > 20:
            remainder -= 14
        
        if 15 <= remainder <= 20:
            results.append("YES")
        else:
            results.append("NO")
    
    print("\n".join(results))

solve()

The solution reads the number of queries and their targets. For each target, it immediately rejects sums below 15. Otherwise, it repeatedly subtracts 14, simulating adding middle dice, until the remainder corresponds to a valid top die configuration (15-20). The choice of 14 comes from the sum of four side faces of a die. This method avoids looping through all possible tower heights and works in constant time per query.

Worked Examples

Consider the sample input 29 34 19 38. We process each:

x Step 1: Check <15 Step 2: Reduce by 14 Remainder Output
29 NO 29>20, subtract 14 → 15 15 YES
34 NO 34>20, subtract 14 → 20 20 YES
19 NO 19≤20 19 YES
38 NO 38>20, subtract 14 → 24 → 10 10 NO

The table shows that reducing by multiples of 14 always lands us in the correct range for top die visibility or outside the feasible range.

Complexity Analysis

Measure Complexity Explanation
Time O(t) Each query takes at most a few subtractions; t ≤ 1000
Space O(t) Storing the result strings for each query

Given t ≤ 1000 and simple arithmetic, this solution executes well within the 1-second time limit and the 256 MB memory limit.

Test Cases

import sys, io

def run(inp: str) -> str:
    sys.stdin = io.StringIO(inp)
    out = io.StringIO()
    sys.stdout = out
    solve()
    return out.getvalue().strip()

# Provided samples
assert run("4\n29 34 19 38\n") == "YES\nYES\nYES\nNO", "sample 1"

# Custom cases
assert run("3\n14 15 20\n") == "NO\nYES\nYES", "minimum sums and exact top die"
assert run("2\n1000000000000000000 999999999999999999\n") == "YES\nYES", "large numbers"
assert run("1\n1\n") == "NO", "impossible tiny sum"
assert run("1\n21\n") == "NO", "just above top die max without middle dice"
Test input Expected output What it validates
14 15 20 NO YES YES boundary conditions for minimal tower and top die sum
10^18, 10^18-1 YES YES very large inputs, arithmetic correctness
1 NO below minimum sum, must reject
21 NO remainder outside feasible top die range after middle dice reduction

Edge Cases

For a target of 14, the minimum possible with one die is 15. The algorithm correctly outputs NO. For a very large target such as 10^18, the algorithm repeatedly subtracts 14 in theory but is optimized via modulo in implementation; the remainder falls into 15-20, so it outputs YES. For a target of 21, subtracting 14 leaves 7, which is below 15, so the algorithm outputs NO, correctly identifying it as impossible. Each edge case is handled by the same remainder logic, guaranteeing correctness.