Comprehensive Guide to AtCoder Beginner Contest 008 Algorithms

Problem A

Problem Statement

Given two integers S and T where S ≤ T, determine the count of positive integers within the inclusive range [S, T].

Approach

The number of integers in a contiguous sequence from S to T is calculated directly by subtracting the start value from the end value and adding one. The formula is simply T - S + 1.

Code Implementation

#include <iostream>

void solve() {
    int s, t;
    std::cin >> s >> t;
    int result = t - s + 1;
    std::cout << result << "\n";
}

int main() {
    solve();
    return 0;
}

Problem B

Problem Statement

Given n strings, identify which character appears most frequently across all of them.

Approach

To efficiently track character counts without high overhead from string comparisons, we can utilize double hashing. Instead of inserting raw strings into a map, we compute a pair of hash values for each unique string. This reduces memory usage and comparison costs.

Key steps include:

  1. Compute two polynomial rolling hashes for each string using different bases and moduli.
  2. Store the hash pair as a key in a frequency map.
  3. Track the maximum frequency encountered during insertion.
  4. Maintain a secondary mapping from the hash key back to the original string for retrieval.

Code Implementation

#include <iostream>
#include <vector>
#include <string>
#include <map>

using namespace std;

const int MOD1 = 1e9 + 7;
const int BASE1 = 131;
const int MOD2 = 1e9 + 9;
const int BASE2 = 137;

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    if (!(cin >> n)) return 0;

    map<pair<long long, long long>, int> freq;
    map<pair<long long, long long>, string> lookup;
    int max_count = 0;
    pair<long long, long long> best_key = {0, 0};

    for (int i = 0; i < n; ++i) {
        string s;
        cin >> s;
        
        long long h1 = 0, h2 = 0;
        for (char c : s) {
            h1 = (h1 * BASE1 + c) % MOD1;
            h2 = (h2 * BASE2 + c) % MOD2;
        }
        
        pair<long long, long long> key = {h1, h2};
        freq[key]++;
        
        if (freq[key] > max_count) {
            max_count = freq[key];
            best_key = key;
        }
        if (lookup.find(key) == lookup.end()) {
            lookup[key] = s;
        }
    }

    cout << lookup[best_key] << endl;
    return 0;
}

Problem C

Problem Statement

There are n coins with values a_1, ..., a_n. Initially, all coins are heads up. For every coin at index i (from left to right), flip all subsequent coins j (where j > i) if a_j is a multiple of a_i. Calculate the expected number of heads remaining after this process.

Approach

Calculating permutations for small N (N ≤ 8) allows direct simulation. However, for larger N, we leverage Linearity of Expectation.

For a specific coin at position i with value v, it remains heads up if an even number of coins to its left have values that divide v (including itself). If there are k divisors in the array including the current one, the probability depends on the parity of the position among these specific elements.

Specifically, if a coin has k related items (divisors), the probability it ends up heads is ceil(k / 2) / k. We sum these probabilities over all coins.

Code Implementation

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; ++i) cin >> a[i];

    double expected_heads = 0.0;

    for (int i = 0; i < n; ++i) {
        int divisor_count = 0;
        for (int j = 0; j < n; ++j) {
            // Check divisibility condition
            if (a[i] % a[j] == 0) {
                divisor_count++;
            }
        }
        // Probability calculation based on divisor count
        // Number of heads contribution is ceil(count/2) / count
        double prob = ((double)(divisor_count + 1) / 2) / divisor_count;
        expected_heads += prob;
    }

    cout.precision(10);
    cout << fixed << expected_heads << endl;
    return 0;
}

Problem D

Problem Statement

Consider a grid of width W and height H containing gold blocks. There are N collectors located at specific coordinates. Collectors expand outward in four cardinal directions collecting available blocks until they stop. Determine the maximum number of gold blocks collected by arranging the order of collector expansion optimally.

Approach

This problem can be modeled using Dynamic Programming with memoization on rectangular regions.

A state is defined by a rectangle bounded by (x1, y1) and (x2, y2). To calculate the optimal collection for a region, we iterate through all collectors inside the current rectangle. Each collector acts as a pivot, splitting the rectangle into four smaller sub-rectangles (top-left, top-right, bottom-left, bottom-right). The score for choosing a pivot is the perimeter length of the expanded arms plus the recursive results of the four sub-regions.

Since only rectangles formed by coordinate boundaires matter, the state space is optimized significantly compared to full grid DP.

Code Implementation

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <functional>

using namespace std;

int W, H, N;
struct Point { int x, y; };
vector<Point> collectors;
map<vector<int>, int> memo;

int solve_region(int x1, int y1, int x2, int y2) {
    vector<int> state = {x1, y1, x2, y2};
    if (memo.count(state)) return memo[state];

    int max_val = 0;

    // Iterate over collectors located within this bounding box
    for (const auto& p : collectors) {
        if (p.x >= x1 && p.x <= x2 && p.y >= y1 && p.y <= y2) {
            // Calculate score: Perimeter contribution + Recursive splits
            int current_score = (x2 - x1 + 1) + (y2 - y1 + 1) - 1;
            current_score += solve_region(x1, y1, p.x - 1, p.y - 1);
            current_score += solve_region(p.x + 1, y1, x2, p.y - 1);
            current_score += solve_region(x1, p.y + 1, p.x - 1, y2);
            current_score += solve_region(p.x + 1, p.y + 1, x2, y2);

            max_val = max(max_val, current_score);
        }
    }

    return memo[state] = max_val;
}

int main() {
    cin >> W >> H >> N;
    collectors.resize(N);
    for (int i = 0; i < N; ++i) {
        cin >> collectors[i].x >> collectors[i].y;
    }

    int result = solve_region(1, 1, W, H);
    cout << result << endl;

    return 0;
}

Posted on Tue, 07 Jul 2026 17:07:13 +0000 by RonDahl