michimani.net

AtCoder Beginner Contest 416 の A/B/C/D 問題の解法 #ABC416

2025-07-26

AtCoder Beginner Contest 416 の A/B/C/D 問題の解法。

実装はこちら atcoder/abc/401-500/416 · michimani/atcoder

A - Vacation Validation

A - Vacation Validation

文字列 \(S\) の \(l\) 番目から \(r\) 番目までの文字がすべて 'o' であるかを確認する。

配列のインデックスは0から始まるので、 \(i\) を \(l-1\) から \(r-1\) まで回して、 \(S[i]\) が 'o' でない場合は "No" を出力する。すべて 'o' であれば "Yes" を出力する。

#include <iostream>

using namespace std;
using ui = unsigned int;
using ull = unsigned long long;
using ll = long long;

int main()
{
  ui n, l, r;
  cin >> n >> l >> r;

  string s;
  cin >> s;

  for (ui i = l - 1; i < r; i++)
  {
    if (s[i] != 'o')
    {
      cout << "No" << endl;
      return 0;
    }
  }

  cout << "Yes" << endl;

  return 0;
}

B - 1D Akari

B - 1D Akari

各位置について、現在までの最後に配置された 'o' の位置を記録し、その位置から現在の位置まで間に '#' があるかを確認する。

'#' でない位置を順番に確認し、直前の 'o' との間に '#' がある場合にのみ 'o' を配置し、それ以外は '.' を配置する。

#include <iostream>

using namespace std;
using ui = unsigned int;

int main()
{
  string s;
  cin >> s;

  string t = s;
  int last_o = -2;

  for (ui i = 0; i < s.length(); i++)
  {
    if (s[i] == '#')
      continue;

    bool can_place = true;
    if (last_o >= 0)
    {
      bool has_hash = false;
      for (int j = last_o + 1; j < (int)i; j++)
      {
        if (s[j] == '#')
        {
          has_hash = true;
          break;
        }
      }

      if (!has_hash)
        can_place = false;
    }

    if (can_place)
    {
      t[i] = 'o';
      last_o = i;
    }
    else
    {
      t[i] = '.';
    }
  }

  cout << t << endl;

  return 0;
}

C - Concat (X-th)

C - Concat (X-th)

\(n\) 個の文字列から \(k\) 個を選んで重複を許して並べ、全ての組み合わせを辞書順に並べたときの \(x\) 番目の文字列を求める。

再帰関数 generate を使って、すべての可能な長さ \(k\) の列を生成する。各位置で \(n\) 個の文字列すべてを試し、結果を vector<string> results に保存する。

最後に results を辞書順にソートし、 \(x-1\) 番目(0-indexedなので)の要素を出力する。

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

using namespace std;

using ui = unsigned int;

int main()
{
  ui n, k, x;
  cin >> n >> k >> x;

  vector<string> s(n);
  for (ui i = 0; i < n; i++)
  {
    cin >> s[i];
  }

  vector<string> results;

  function<void(vector<int> &, int)> generate = [&](vector<int> &seq, ui pos)
  {
    if (pos == k)
    {
      string result = "";
      for (ui i = 0; i < k; i++)
      {
        result += s[seq[i]];
      }
      results.push_back(result);
      return;
    }

    for (ui i = 0; i < n; i++)
    {
      seq[pos] = i;
      generate(seq, pos + 1);
    }
  };

  vector<int> seq(k);
  generate(seq, 0);

  sort(results.begin(), results.end());

  cout << results[x - 1] << endl;

  return 0;
}

D - Match, Mod, Minimize 2

D - Match, Mod, Minimize 2

各テストケースごとに、配列 \(a\) と \(b\) をソートし、各 \(b_i\) に対して最適な \(a_j\) を選ぶ。

\((b_i + a_j) \bmod m\) を最小化したいので、 \(a_j \geq m - b_i\) となる最小の \(a_j\) を見つける。それと、最小の \(a\) 要素との結果を比較し、より小さい値を選ぶ。

multiset を使用して利用可能な \(a\) の値を管理し、選ばれた値は削除する。

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;
using ui = unsigned int;
using ll = long long;

int main()
{
  ui t;
  cin >> t;

  for (; t--;)
  {
    ui n;
    ll m;
    cin >> n >> m;

    vector<ll> a(n), b(n);
    for (ui i = 0; i < n; i++)
      cin >> a[i];
    for (ui i = 0; i < n; i++)
      cin >> b[i];

    sort(a.begin(), a.end());
    sort(b.begin(), b.end());

    ll total = 0;
    multiset<ll> available(a.begin(), a.end());

    for (ui i = 0; i < n; i++)
    {
      ll bi = b[i];
      ll target = m - bi;
      
      auto it = available.lower_bound(target);
      ll best_val = (bi + *available.begin()) % m;
      auto best_it = available.begin();
      
      if (it != available.end())
      {
        ll val = (bi + *it) % m;
        if (val < best_val)
        {
          best_val = val;
          best_it = it;
        }
      }
      
      if (it != available.begin())
      {
        --it;
        ll val = (bi + *it) % m;
        if (val < best_val)
        {
          best_val = val;
          best_it = it;
        }
      }

      total += best_val;
      available.erase(best_it);
    }

    cout << total << endl;
  }

  return 0;
}

comments powered by Disqus