Algorithmic Solutions to AtCoder Beginner Contest 057

Problem A: 24-Hour Time Calculation

Given the current time $A$ and a duration $B$ in hours, the task is to determine the start time of an event using a 24-hour clock format. Since the clock cycles every 24 hours, the solution involves a simple modular arithmetic operation.

The resulting time is calculated as $(A + B) \pmod{24}$.

#include <iostream>

int main() {
    int current_hour, duration;
    std::cin >> current_hour >> duration;
    
    int start_time = (current_hour + duration) % 24;
    std::cout << start_time << std::endl;
    
    return 0;
}

Problem B: Nearest Checkpoint Assignment

We are given $N$ students and $M$ checkpoints on a 2D plane. Each student moves to the checkpoint closest to them in terms of Manhattan distance. If multiple checkpoints share the same minimal distance, the student chooses the one with the smallest index.

The constraints are $1 \le N, M \le 50$ and coordinates can be as large as $10^{18}$.

For each student, we sort the checkpoints based on the Manhattan distance to that student, using the checkpoint index as a tie-breaker. The first checkpoint in the sorted list is the answer for that student.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>

int main() {
    int num_students, num_checkpoints;
    std::cin >> num_students >> num_checkpoints;

    struct Point { long long x, y; };
    struct Checkpoint { Point pos; int id; };

    std::vector<Point> students(num_students);
    for (auto& s : students) {
        std::cin >> s.x >> s.y;
    }

    std::vector<Checkpoint> checkpoints(num_checkpoints);
    for (int i = 0; i < num_checkpoints; ++i) {
        std::cin >> checkpoints[i].pos.x >> checkpoints[i].pos.y;
        checkpoints[i].id = i + 1;
    }

    auto get_distance = [](const Point& p1, const Point& p2) {
        return std::abs(p1.x - p2.x) + std::abs(p1.y - p2.y);
    };

    for (const auto& student : students) {
        std::sort(checkpoints.begin(), checkpoints.end(), 
            [&](const Checkpoint& a, const Checkpoint& b) {
                long long dist_a = get_distance(student, a.pos);
                long long dist_b = get_distance(student, b.pos);
                if (dist_a != dist_b) return dist_a < dist_b;
                return a.id < b.id;
            });
        
        std::cout << checkpoints[0].id << "\n";
    }

    return 0;
}

Problem C: Digit Minimization via Factorization

Given an integer $N$ ($1 \le N \le 10^{10}$), we must find positive integers $A$ and $B$ such that $N = A \times B$. The objective is to minimize $F(A, B)$, defined as the maximum of the number of digits in $A$ and the number of digits in $B$.

We can iterate through all factors $i$ of $N$ from $1$ up to $\sqrt{N}$. For each factor $i$, the corresponding pair is $(i, N/i)$. We calculate the digit count for both and keep track of the minimum maximum value found.

#include <iostream>
#include <algorithm>

int count_digits(long long val) {
    int length = 0;
    while (val) {
        val /= 10;
        length++;
    }
    return length;
}

int main() {
    long long N;
    std::cin >> N;

    int min_max_digits = 11; 
    for (long long i = 1; i * i <= N; ++i) {
        if (N % i == 0) {
            long long a = i;
            long long b = N / i;
            int digits_a = count_digits(a);
            int digits_b = count_digits(b);
            min_max_digits = std::min(min_max_digits, std::max(digits_a, digits_b));
        }
    }
    std::cout << min_max_digits << "\n";
    return 0;
}

Problem D: Maximizing Average Value

Given $N$ items with values $v_i$, select $x$ items where $A \le x \le B$ to maximize the arithmetic mean of the selected values. We must output the maximum average and the number of ways to achieve it.

To maximize the average, we should always select the items with the largest values. We sort the array in descending order. Let the sorted array be $a$. The maximum average is the average of the first $A$ elements.

The challenge lies in counting the valid combinations. Let $a[A-1]$ be the value at the boundary of the selection. Let $total$ be the total number of elements in the array equal to $a[A-1]$, and $selected$ be the number of elements equal to $a[A-1]$ within the first $A$ elements.

Case 1: If $a[0] == a[A-1]$, it means the first $A$ elements are all the maximum value. In this case, we can select any number of items $k$ from $A$ up to $\min(B, total)$. The total number of ways is $\sum_{k=A}^{\min(B, total)} \binom{total}{k}$.

Case 2: If $a[0] \neq a[A-1]$, then $a[A-1]$ is strictly less than the maximum value. Adding any more items beyond $A$ would lower the average. Thus, we must select exactly $A$ items. The items strictly greater than $a[A-1]$ are mandatory selections. We need to choose the remaining $selected$ items from the $total$ available items with value $a[A-1]$. The number of ways is $\binom{total}{selected}$.

#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>
#include <numeric>

long long comb[55][55];

void build_combinations() {
    for (int i = 0; i < 55; ++i) {
        comb[i][0] = comb[i][i] = 1;
        for (int j = 1; j < i; ++j) {
            comb[i][j] = comb[i-1][j-1] + comb[i-1][j];
        }
    }
}

int main() {
    build_combinations();

    int N, A, B;
    std::cin >> N >> A >> B;
    
    std::vector<long long> vals(N);
    for (int i = 0; i < N; ++i) std::cin >> vals[i];
    
    std::sort(vals.begin(), vals.end(), std::greater<long long>());
    
    double sum = std::accumulate(vals.begin(), vals.begin() + A, 0.0);
    double avg = sum / A;
    
    std::cout << std::fixed << std::setprecision(10) << avg << std::endl;
    
    long long ways = 0;
    long long boundary_val = vals[A - 1];
    
    long long total_count = 0; // Total occurrences of boundary_val in array
    long long prefix_count = 0; // Occurrences of boundary_val in first A elements
    
    for (auto v : vals) if (v == boundary_val) total_count++;
    for (int i = 0; i < A; ++i) if (vals[i] == boundary_val) prefix_count++;
    
    if (vals[0] == boundary_val) {
        // Case 1: All selected items are max value, can select more up to B
        int limit = std::min(B, (int)total_count);
        for (int k = A; k <= limit; ++k) {
            ways += comb[total_count][k];
        }
    } else {
        // Case 2: Must select exactly A items
        ways = comb[total_count][prefix_count];
    }
    
    std::cout << ways << std::endl;
    
    return 0;
}

Tags: competitive-programming algorithms AtCoder cpp combinatorics

Posted on Mon, 10 Aug 2026 16:46:33 +0000 by Jimmy_uk