Official

A - 財布の中身 / Contents of the Wallet Editorial by admin

swe-2-high

解法

問題の要求は、文字列 \(S\) の中に C(硬貨)と B(紙幣)が両方とも少なくとも \(1\) 回出現するかを判定することです。

アルゴリズム

  1. \(N\) と文字列 \(S\) を読み込む。
  2. \(S\) を走査し、C が出現したかを記録するフラグ hasC と、B が出現したかを記録するフラグ hasB を更新する(あるいは、言語組み込みの部分文字列・文字探索機能を使う)。
  3. hasC と hasB が両方とも真なら Yes を、そうでなければ No を出力する。

正当性の証明

hasC は走査終了時点で「\(S\) の中に C が \(1\) 文字以上存在する」ことと同値になります。実際、走査では各文字を漏れなく 1 回ずつ調べ、C を見つけたときのみ hasC が真になるため、C が存在すれば真に、存在しなければ偽のままです。hasB についても同様です。

出力される答えは hasC && hasB が真のとき Yes、偽のとき No です。\(S\) は C と B のみからなるため、「硬貨と紙幣が両方とも \(1\) 枚以上入っている」という条件は「C が存在し、かつ B が存在する」と同値です。したがってこのアルゴリズムは問題の要求と正確に一致します。

\(N = 1\) の場合は \(S\) が 1 文字しか持たないので、必ず C か B のどちらか一方のみであり、正しく No が出力されます。

計算量

  • 時間計算量: \(O(N)\)(各文字を 1 回ずつ調べる)
  • 空間計算量: 入力文字列 \(S\) の保持に \(O(N)\)、補助的な領域はフラグのみで \(O(1)\)

なお、Python 実装では 'C' in S と 'B' in S を使っており、C++ 実装では明示的なループを使っていますが、どちらも本質的に同じ判定を行っています。