AtCoder Beginner Contest 418 C,D,E,F問題メモ

AtCoder Beginner Contest 418

全体的に難しかった印象。

なお今回ティーポットの問題が多かった理由は、HTTP レスポンスステータスコード(404 Not Found とかのアレ)関連のジョークで、 418 が「I'm a teapot」と定義されていたことによると思われる。

C - Flush

問題文

  • ポーカーテーブルの上に $N$ 種類のフレーバーのティーバッグが置かれています。
  • フレーバー $i$ ($1 \leq i \leq N$) のティーバッグは $A_i$ 個あります。
  • あなたはこれらのティーバッグを使ったゲームに参加します。
  • ゲームには $1$ 以上 $A_1 + \dots + A_N$ 以下の難易度が設定されており,難易度 $b$ のゲームは以下の流れで行われます。
    • あなたは整数 $x$ を宣言する。このとき、$b \leq x \leq A_1 + \dots + A_N$ を満たす必要がある。
    • ディーラーはポーカーテーブルの上にあるティーバッグの中からちょうど $x$ 個を選び、あなたに渡す。
    • あなたは渡された $x$ 個のティーバッグのフレーバーを確認し、その中から $b$ 個のティーバッグを選ぶ。
    • あなたが選んだ $b$ 個のティーバッグがすべて同じフレーバーであれば、あなたは勝利する。そうでなければ、あなたは敗北する。
  • ディーラーはあなたが敗北するように最善を尽くすものとします。
  • $Q$ 個の質問が与えられるので、それぞれに答えてください。$j$ 番目の質問は以下の通りです。
    • 難易度 $B_j$ のゲームに勝利するためにはじめに宣言する必要がある整数 $x$ の最小値を答えよ。勝利が不可能であれば、代わりに $-1$ と答えよ。

制約

  • $1 \leq N \leq 3 \times 10^5$
  • $1 \leq Q \leq 3 \times 10^5$
  • $1 \leq A_i \leq 10^6$ ($1 \leq i \leq N$)
  • $1 \leq B_j \leq \min(10^6, A_1 + \dots + A_N)$ ($1 \leq j \leq Q$)
  • 入力される値は全て整数である。

解法

C問題からわりと難しい。

難易度 $b$ が決まれば、ディーラーがあなたを敗北させられる $x$ の上限も決まる。
ディーラーにとっては、各フレーバー $i$ について $\min(A_i,b-1)$ 個だけ渡すようにするのが最善である。
あなたはそれより1つ多い $\displaystyle 1+\sum_{i=1}^{N}\min(A_i,b-1)$ を $x$ に指定すれば勝てる。

b-1 ________________▊__
            ▊   ▊   ▊
        ▊   ▊   ▊   ▊
    ▊   ▊   ▊   ▊   ▊
i   1   2   3   4   5           あなたは b=4 の時 
    1 + 2 + 3 + 3 + 3  =  12    x=13 を指定すれば勝てる

愚直にこれを求めるとクエリ1回に $O(N)$ かかるので、全体 $O(NQ)$ でTLEとなる。

$i$ について横に足していくと $b$ が変化したときに最初から計算しなおしになるので効率が悪い。
クエリを先読みしておき、$b$ を増やしながら足すものを横に見ていくと、様々な $b$ について1回のイテレートで完結できる。

↑b-1________________▊__
↑           ▊   ▊   ▊  + 3 = 12
↑       ▊   ▊   ▊   ▊  + 4 =  9
↑   ▊   ▊   ▊   ▊   ▊    5 =  5
↑i  1   2   3   4   5

足す数は $N$ からスタートし、$A_i=b$ である $A_i$ 1つにつき、1減っていく。

注意点として、$b-1 \ge \max(A)$ の時は、全ティーバッグを渡されても $b$ 個を選べず、負けが確定する。
$b-1$ を増やすのは、$\max(A)-1$ までとなる。

Python3

D - XNOR Operation

問題文

  • '0' と '1' からなる空でない文字列 $S$ が次の条件を満たす時、$S$ を美しい文字列と呼びます。
    • (条件) 次の一連の操作を $S$ の長さが $1$ になるまで行い、$S$ に残った唯一の文字を '1' にすることができる。
      • $1 \leq i \leq |S| - 1$ を満たす整数 $i$ を自由に選ぶ。
      • 整数 $x$ を次のように定義する。
        • $S_i =$ '0' かつ $S_{i+1}=$ '0' である場合、$x = 1$ とする。
        • $S_i =$ '0' かつ $S_{i+1}=$ '1' である場合、$x = 0$ とする。
        • $S_i =$ '1' かつ $S_{i+1}=$ '0' である場合、$x = 0$ とする。
        • $S_i =$ '1' かつ $S_{i+1}=$ '1' である場合、$x = 1$ とする。
      • $S_i$ と $S_{i+1}$ を取り除き、それらがあった場所に $x$ を数字とみなしたものを $1$ 個挿入する。
        • 例えば $S=$ '10101' に対して $i=2$ を選んで操作を行った場合、操作後の文字列は '1001' になる。
  • '0' と '1' からなる長さ $N$ の文字列 $T$ があります。
  • $T$ の部分文字列である美しい文字列の個数を求めてください。
    • ただし、$2$ つの部分文字列が文字列として同じでも、取り出す位置が異なるならば別々に数えます。

制約

  • $1 \leq N \leq 2 \times 10^5$
  • $N$ は整数
  • $T$ は '0' と '1' からなる長さ $N$ の文字列

解法

美しい文字列の特徴を見つけるため、操作を逆順におこなって実験してみる。
'1'からスタートし、「'1'を'00'または'11'に」「'0'を'01'または'10'に」置き換えていく中でできる文字列が 美しい文字列である。

すると、以下の事実に気付く。

  • 長さ $n$ の美しい文字列は $2^{n-1}$ 通り
  • 含まれる'1'の数は、奇数長の文字列なら奇数個、偶数長の文字列なら偶数個

改めて考えてみると、1回のNXORの変換によって、'1'の個数の偶奇は必ず変化する。
偶奇のルールさえ守っていればどんな文字列でもできるのか、という証明はできてないが、 まぁ実験結果が綺麗に揃ってるので大丈夫だろうと信じて、以下を数える。

  • $T$ に含まれる、「奇数長で'1'を奇数個含む部分文字列」「偶数長で'1'を偶数個含む部分文字列」

これは累積和の考え方を応用して、以下の4種類に分けて個数を記録しておけば

  • $T$ の先頭 $i$ 文字目までの中に、$j$ 個の'1'が出現する時、$c_{i \% 2, j \% 2}+=1$

区間の両端の選び方は以下の6通りが条件を満たす。

  • (偶数長,偶数個)
    • $c_{0,0}$ から2つ選ぶ
    • $c_{0,1}$ から2つ選ぶ
    • $c_{1,0}$ から2つ選ぶ
    • $c_{1,1}$ から2つ選ぶ
  • (奇数長,奇数個)
    • $c_{0,0}$ から1つ、$c_{1,1}$ から1つ選ぶ
    • $c_{0,1}$ から1つ、$c_{1,0}$ から1つ選ぶ

$c_{0,0}$ と $c_{1,1}$ から1つずつ選ぶ場合などは、どちらが先であってもよいので、個数だけで考えられる。

Python3

E - Trapezium

問題文

  • 二次元平面上に $N$ 個の点があり、$i$ 番目の点は座標 $(X_i, Y_i)$ にあります。
  • どの $2$ 点も相異なる位置にあり、どの $3$ 点も同一直線上にないことが保証されます。
  • これらの点から $4$ 点を選ぶ組合せのうち、その $4$ 点を頂点とする多角形として台形がとれるものは何通りありますか?
    • 平行四辺形、長方形、正方形も台形の一種と数えます。

制約

  • $4 \leq N \leq 2\,000$
  • $0 \leq X_i, Y_i \leq 10^7$ ($1 \leq i \leq N$)
  • どの $2$ 点も相異なる位置にある。
  • どの $3$ 点も同一直線上にない。
  • 入力される値は全て整数である。

解法

どの3点も同一線上にないという制約がありがたく、かなり考えるパターンを減らせる。

2点間の「傾き」ごとに、その傾きになる2点組の数をカウントする。
同じ傾きを持つ2点組から2個を選べば、その4点が台形となる。
どの3点も同一線上にないので、「選んだ4点に同じ点が含まれる」や「同一直線上にある4点を選んでしまう」心配は無い。

整数座標の2点の傾きは、2点間の差を $dx,dy$ とした時、たとえば以下のようにすると標準化できる。

  • 互いに素にする。$g=\gcd(dx,dy)$ とし、$dx←dx/g, dy←dy/g$
  • $dx \ge 0$ にする。$dx \lt 0$ の場合は $dx,dy$ ともに $-1$ 倍する。
  • $dx=0$ の時、$dy \ge 0$ にする。

標準化した $(dx,dy)$ をキーとしてカウントすれば、長さや向きが違っても同一視して平行な線分を数えられる。

傾き $(dx,dy)$ を持つ線分の個数を $C_{dx,dy}$ とすると、 その中から2個を選ぶのは $\dfrac{C_{dx,dy}(C_{dx,dy}-1)}{2}$ 通り。
全てのあり得る傾きについてこれを合計すると、答えとなる、、、?

実は平行四辺形(長方形、正方形含む)が2通りの対辺で重複して数えられてしまっているため、引く必要がある。

  _____
 /    /    平行四辺形1つにつき、/ と __ で 2回カウントされる
/____/     → 平行四辺形の数だけ引く必要がある

平行四辺形は、対辺の長さが同じになる。つまり、上記の標準化の過程での $g$ が同じになる。

よって、上記とは別に $(dx,dy,g)$ をキーとしたカウントもおこない、同じキーの中から2個選ぶと平行四辺形となる。
この時も平行四辺形は2回ずつ数えられてしまっているので、総和の半分を答えから引くことで、重複がのぞける。

Python3


平行四辺形の数え方について、「対頂点の中点」が一致するという性質を使うこともできる。

そこまで大きく変わらないが、こちらの方が計算が楽かも。

全ての2点組について $(x_1+x_2,y_1+y_2)$ をキーとしてカウントし、同じになった“2点組の2つ組”の個数を数えればよい。

F - We're teapots

問題文

  • $N$ 個のティーポットが横一列に並んでおり、左から順に $1$ から $N$ までの番号が付けられています。
  • 整数列 $(a_1, \dots, a_N)$ があり、はじめその値は $a_1 = \dots = a_N = -1$ です。
  • あなたは以下の条件をすべて満たすように、それぞれのティーポットに紅茶かコーヒーのいずれか $1$ つを入れます。
    • どの隣り合う $2$ つのティーポットについても、少なくとも片方には紅茶を入れる。
    • $1 \leq i \leq N$ を満たす整数 $i$ について、$a_i \neq -1$ である場合、ティーポット $1, \dots, i$ のうちちょうど $a_i$ 個にコーヒーを入れる。
  • クエリが $Q$ 個与えられるので、与えられた順に処理してください。
  • $j$ 番目のクエリ ($1 \leq j \leq Q$) は以下の通りです。
    • $a_{X_j}$ の値を $Y_j$ に変更する。その後、条件を満たすようなティーポットの満たし方の個数を $998244353$ で割ったあまりを出力する。

制約

  • $2 \leq N \leq 2 \times 10^5$
  • $1 \leq Q \leq 2 \times 10^5$
  • $1 \leq X_j \leq N$ ($1 \leq j \leq Q$)
  • $-1 \leq Y_j \leq X_j$ ($1 \leq j \leq Q$)
  • 入力される値は全て整数である。

解法

複雑なセグメント木。
「こんな感じのことをすると解ける」というのはわかっても、実装に時間がかかってしまう。

紅茶を0、珈琲を1で表す。
「1が連続しない、かつ、先頭からの累積和が $a_i$ の条件を満たすような、長さ $N$ の $0,1$ 列の数」を数えればよい。

そのような列を、$B=(B_1,...,B_N)$ とする。

セグメント木に以下を載せる。
ノードが表す区間内で、「最も左の'-1'以外の制約」がある位置を $l$、「最も右の'-1'以外の制約」がある位置を $r$ とする。

  • 1) 最も左の制約の値 $a_{l}$
  • 2) $l$ より左にある区間内の $a$ の'-1'の個数
  • 3) 最も右の制約の値 $a_{r}$
  • 4) $r$ より右にある区間内の $a$ の'-1'の個数
  • 5) ノードが表す区間の $a$ が全て '-1' フラグ
  • 6) $B_l=0,B_r=0$ の場合の $B_{l,...,r}$ の配置方法の数
  • 7) $B_l=1,B_r=0$ の場合の $B_{l,...,r}$ の配置方法の数
  • 8) $B_l=0,B_r=1$ の場合の $B_{l,...,r}$ の配置方法の数
  • 9) $B_l=1,B_r=1$ の場合の $B_{l,...,r}$ の配置方法の数

5)がTrueの場合、1,3は意味を持たず、2,4は区間長が入り、6,7,8,9は $0$ とする。

6)~9)は、あくまで「$l,...,r$ への配置方法」であり、左右端から続く'-1'への配置は後で別途計算するとする。

i   |           l             r            |    | |:ノードが表す区間
a   |... -1 -1  5  -1 ... -1  8  -1 -1 ... |
B   |--未確定-- 0 ---確定---  0 --未確定-- |    → 6)で数える
    |--未確定-- 1 ---確定---  0 --未確定-- |    → 7)で数える
    |--未確定-- 0 ---確定---  1 --未確定-- |    → 8)で数える
    |--未確定-- 1 ---確定---  1 --未確定-- |    → 9)で数える
     ~~~~~~~~~~                 ~~~~~~~~~~
     <- 2)個 ->                 <- 4)個 ->

区間外の制約が不明な状態で左右端の'-1'の $B_i$ まで決めてしまうと、 左右ノードとのマージ時に制約に矛盾しないかの確認のため 「そこに'1'を何個置いたか」を管理しなければならず、状態数が $O(N^2)$ となってしまう。

未確定の部分は“左右の制約に挟まれて”はじめて 「何個中、何個を'1'にすればよいか」というのが決まるので、それまでは保留とする。
その計算の際、$B_l,B_r$ が $0,1$ のどちらかによって、 $B_{l-1}$ や $B_{r+1}$ を'1'にできるかどうかが変わるため、6)~9)の場合分けが必要となる。

$n$ 個中、ちょうど $m$ 個を隣接させずに'1'にするには、 「$n-m$ 個の'0'を並べた後、両端を含めた $n-m+1$ 個の隙間のうち '1'を挿入する $m$ 箇所を選ぶ」と考えると、 ${}_{n-m+1}C_{m}$ で求められる。$n-m+1 \lt m$ だったりすると $0$ 通り。

ノード $P$ と $Q$ のマージを考える。
ノード $P$ の 1) の値を $P_1$ などと表す。

両者の間には、$P_4+Q_2$ 個の未確定('-1')が並ぶため、 そこに $Q_1-P_3$ 個の'1'を置くパターン数を求めれば良い。

     P        ] [        Q
i  r           |            l
a  8 -1 ... -1 | -1 ... -1 12 -1 ...
B  0           |            0
     ~~~~~~~~~~~~~~~~~~~~~
     P4+Q2 の区間に 12-8=4 個の1が必要

ただし、$B_r,B_l$ に置いた数によって、以下の調整が必要となる。

  • $B_r$ が'1'だと、'1'を置ける範囲が1減る
  • $B_l$ が'1'だと、'1'を置ける範囲が1減る
  • $B_l$ が'1'だと、'1'を置く必要数は1減る
     P        ] [        Q
i  r           |            l
a  8 -1 ... -1 | -1 ... -1 12 -1 ...
B  0           |         x  1
     ~~~~~~~~~~~~~~~~~~~
     Bl=1の場合は、P4+Q2-1 の区間に 3 個の1が必要

この際、$P_4+Q_2=0$ や、$a_r=a_l$ の場合に少し注意。
区間長や置くべき1の個数が負になったまま計算してしまわないように、丁寧な場合分けが必要となる。
(この辺にどうしても時間がかかってしまう)

ともかく、これで全体をマージした後、左右の未確定部分を改めて決めてやれば、答えが求められる。

右の未確定部分については、長さは決まっているが、この内いくつを'1'にするのか、という個数制限はない。
この場合のパターン数は、逆に $0$ とする位置を決めるDPを考えればフィボナッチ数列となるので、前計算できる。

Python3

G - Binary Operation

問題文

  • $A, B, C, D \in \lbrace 0, 1 \rbrace$ を満たす整数の組 $(A, B, C, D)$ は $16$ 通りあります。
  • それぞれに対して次の問題を解いてください。
  • '0' と '1' からなる空でない文字列 $S$ が次の条件を満たす時、$S$ を美しい文字列と呼びます。
    • (条件) 次の一連の操作を $S$ の長さが $1$ になるまで行い、$S$ に残った唯一の文字を '1' にすることができる。
      • $1 \leq i \leq |S| - 1$ を満たす整数 $i$ を自由に選ぶ。
      • 整数 $x$ を次のように定義する。
        • $S_i =$ '0' かつ $S_{i+1}=$ '0' である場合、$x = A$ とする。
        • $S_i =$ '0' かつ $S_{i+1}=$ '1' である場合、$x = B$ とする。
        • $S_i =$ '1' かつ $S_{i+1}=$ '0' である場合、$x = C$ とする。
        • $S_i =$ '1' かつ $S_{i+1}=$ '1' である場合、$x = D$ とする。
      • $S_i$ と $S_{i+1}$ を取り除き、それらがあった場所に $x$ を数字とみなしたものを $1$ 個挿入する。
        • 例えば $S=$ '10101' に対して $i=2$ を選んで操作を行った場合、操作後の文字列は $B=0$ の場合 '1001' に、$B=1$ の場合 '1101' になる。
  • '0' と '1' からなる長さ $N$ の文字列 $T$ があります。
  • $T$ の部分文字列である美しい文字列のうち最長のものの長さを $L$ (ただし、$T$ の部分文字列である美しい文字列が存在しない場合は $L = -1$ とする)、$T$ の部分文字列である美しい文字列の個数を $M$ とします。$L$ および $M$ を求めてください。
  • ただし、$2$ つの部分文字列が文字列として同じでも、取り出す位置が異なるならば別々に数えます。

制約

  • $1 \leq N \leq 2 \times 10^5$
  • $N$ は整数
  • $T$ は '0' と '1' からなる長さ $N$ の文字列

解法

D問題では、この中の $(A,B,C,D)=(1,0,0,1)$ というパターンの時の部分問題を解いた。
この場合は「“0”が偶数個ならOK」という条件が発見でき、累積和とindexの偶奇で計算できた。

このように、16通りのパターンそれぞれについて愚直に実験した結果を観察すると、 「先頭が'1'ならOK」など、どれも比較的わかりやすい法則性を持つ。
法則性がわかりにくいパターンもあるが2~3文字までで、4文字以上は単純な条件で表せる。

しかし、いくら単純とはいえ、16通りについて別々の問題を解いていたら1時間くらいは優にかかってしまう。
コンテスト時間の短いABCでは、ある種の TLE 解法(“実装” 時間制限超過)という想定だろう。

想定解は、「美しい文字列が、いずれのパターンでも比較的、状態数の少ないオートマトンで表現できる」ことを利用して、 「オートマトン自動生成→オートマトン上で最大長と個数のDP」をするというもの。

ただ、公式Editorialでは、「状態数の少ないオートマトンで表現できる」ことの証明が 「実際にそうなるから」という説明に留まっている(ように見える?)ので、 なかなかこの解法が正当だと確信を持って実装に移るのは難しいか。

一応、各パターンの美しい文字列が「正規表現」で表せそうなことに気付けば、 「正規表現はオートマトンに変換できる」という知識と合わせて、 この解法に辿り着ける余地はある。

たとえば以下の2通りの解法がある。

  • 正規表現からオートマトン(DFA)への変換ライブラリを利用する。
    • 各パターンで美しい文字列となる正規表現は、実験して個別に推測する。
  • パターン $(A,B,C,D)$ そのものからオートマトンを生成するアルゴリズムを実装する。

公式Editorialの想定解は下の方だが、上の方がおそらく着想から実装までの速度は速そう。
「美しい文字列の正規表現を実験から推測する」のはそんなに1つ1つに時間はかからない。

正規表現からDFAへの変換

正規表現→DFAへの変換の原理は、以下などに記事がある。

今回、正規表現に求められる記号は「*」「()」「|」程度に絞ってよいので、 ChatGPTなどに変換コードをお願いすればパパッと出してくれる。(本番で使うのはアウトだが)

後はそれぞれのパターンで愚直解を観察して正規表現をエスパーすればよい。
やってみると、特に工夫のない正規表現でも、高々20状態くらいのDFAに変換してくれる。

Python3

パターンからDFAへの変換

公式Editorialでの想定解。どのような $(A,B,C,D)$ を与えられてもDFAを自動構築できるアルゴリズムを作る。

DFAをきちんと定義すると、以下の5つの要素からなる。

  • $M=(Q, \Sigma, \sigma, q_0, F)$
  • $Q$: 状態の有限集合(オートマトンの1ノード)
  • $\Sigma$: アルファベット(入力される可能性のある文字の集合)
  • $\sigma$: 遷移関数 $Q \times \Sigma → Q$
  • $q_0 \in Q$: 初期状態
  • $F \subseteq Q$: 受理状態の集合(この状態のどれかに辿り着ければマッチ)

今回の場合、$\Sigma=\{0,1\}$ とする。
$q_0$ は $\epsilon$ 空文字列とする。

$(A,B,C,D)$ が与えられたときに「$M$ が受理する文字列=美しい文字列」 となるように $Q, \sigma, F$ を自動で決めたい。
後のDPでは状態数 $|Q|$ が計算量にかかるため、なるべく状態数が少ないと嬉しい。

超・無思考に自動生成すると、全ての文字列を異なる状態とし、 011 –0→ 0110 みたいに遷移を張り、美しい文字列だけを受理状態とする、というのが一応考えられる。
当然、状態数が無限なので実際の構築は無理。

ここから、「自身を含めた、自身以降の遷移による受理/不受理が完全に同じ状態は同一視」できる。
まぁ、それはそう。

○011 --0→ ×0110 --0→ ○01100 ..  ○1100 --0→ ×11000 --0→ ○110000 ..
     |            `--1→ ×01101 ..        |             `--1→ ×110001 ..
     `--1→ ○0111 --0→ ×01110 ..        `--1→ ○11001 --0→ ×110010 ..
                  `--1→ ○01111 ..                      `--1→ ○110011 ..
○:受理 ×:不受理

→011 と 1100 は同じ状態として良い
(ついでに、0110と11000, 01100と110000なども)

これによって状態数を減らしたいが、この方法も、本当に同一かどうか無限に続く遷移を辿るのは無理。

そこで、「辿るステップ数を限定」してみる。

例えば上記の例では2ステップ目までを辿って以降の表記は省略しているが、実際に辿るのもそこで打ち切り、 (辿るステップ数を $u$ ステップと決めた場合)$u$ ステップ目までの遷移が等しければ「同じ状態」と仮決めする。

$u$ を決めたときに実際のDFAの構築は、BFSのように

  • キューを用意し、空文字列を入れ、以下を空になるまで繰り返す
  • キューから文字列を1つ取り出す($S$ とする)
  • 既に出てきた他の文字列の中に、$u$ ステップ目までの受理/不受理が $S$ と一致するものがあれば、$S$ からは探索を広げない
  • 一致するものが無い場合は、$S$ を表す新しい状態をDFAに追加し、S+'0', S+'1' をキューに追加する

のようにしていけば、いつかは終了する。

既に訪れた状態の記録や、遷移先の復元は、「$u$ ステップ目までの受理/不受理のboolean配列」をキーにしておくとやりやすい。 また、受理/不受理の確認は、$|S|$ がそんなに長くならないことを見越して愚直に操作する位置を全探索すればよい。(メモ化はするといいかも)

これによってできるDFAを $M_u$ とする。

もちろんこれは誤っている(美しい文字列=受理される文字列となっていない)可能性があるが、 $u=0,1,2,...$ と増やしていき、$M_u = M_{u+1}$(つまり、$Q,\sigma,F$ が等しい)状態となったら打ち切る。

今回の問題設定では、これで得られる $M_u$ が、実は正しいDFAを構築できている。。。らしい。

公式Editorialに証明があるが難しい。

  • DFA $M_u$ から、1文字延長して $u+1$ ステップ先に対しても正しく受理されるNFA $M_{u+1}'$ を作る。
  • NFAはDFAに変換できるので、変換してさらに状態数を最小化したものを $M_{u+1}''$ とする。
  • 同じ言語を受理する状態数最小のDFAは一意に決まるということが証明できる。
  • よって、$M_u=M_{u+1}$ なら、$M_{u+1}''=M_{u+1}$
  • これを繰り返せば、$M_u=M_{u+1}=M_{u+2}=...$

最初に $M_u$ から $M_{u+1}'$ を作る具体的な手順がイマイチよくわからない。
NFAは、1つの状態から同じ遷移(0や1の辺)が複数出ていたり、 無条件の(文字を消費しない)遷移があってもよいオートマトンである。
「全ての遷移後に受理状態に存在可能な経路」が1つでもあったら受理される。

  • DFA $M_u$ の遷移 –0→ は、間に状態を補って –0→○–1→ のように置き換えることでステップを1つ増やせる。
    • ※この例は、$B=0$、つまり 01→0 と変換できる場合
  • $u$ ステップの遷移のどれか1箇所を置き換えることで、$u+1$ ステップに拡張できる。

あたりを使うのかなぁとは思うが、じゃあNFAをどう構築するかというと、、、?

まぁ、証明はともかく、このアルゴリズムによってオートマトンを自動生成しDPで解ける。

programming_algorithm/contest_history/atcoder/2025/0809_abc418.txt · 最終更新: by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0