公式

N - Nice Bouquets 解説 by confeito


赤に \(0\) 、緑に \(1\) 、青に \(2\) の値を割り当てます(以下、色をこの \(3\) つの値で表します)。ある日に取れる花について、花を余すことなく適切な花束が作れることは、その日に取れる花の個数が \(3\) の倍数かつ、すべての花に割り当てた値の合計が \(3\) の倍数になることと同値です。

証明

適切な花束が作れるならば、必ず花の個数は $3$ の倍数であり、それぞれの花束に割り当てられる値も $3$ の倍数になる。逆に、その日に取れる花の個数が $3$ の倍数かつ、すべての花に割り当てた値の合計が $3$ の倍数になる場合は以下のようにして花束を構成できる。

① 同じ色の花が $3$ つ以上ある間、それを花束にすることを繰り返す。

② 上記の操作が終わった際、どの色の花も $3$ 個以上存在せず、花の個数は $3$ の倍数であり、さらに残っている花の色に対応する値の合計は $3$ の倍数である。このような条件を満たす花の色の組み合わせは、 $\{\},\{0,1,2\},\{0,0,1,1,2,2\}$ しかありえない。このいずれに対しても、赤緑青の $3$ 色からなる花束を作ることで、花を余さず花束を作れる。

ここで、それぞれの木について、\(K\) 日間の花の色を \(\mathbb{F}_3\) 上の \(K\) 次元ベクトルとして考え、さらに \(K+1\) 次元目として \(1\) を追加します。すると、今後 \(K\) 日間、毎日花が余らないようにできる条件は、それぞれの木を表す \(K+1\) 次元ベクトルの和が \(\bm{0}\) になることと言い換えることができます。また、木を切ることは、ベクトルを \(1\) つ削除する操作、促進剤をかけることは、ベクトルを \(2\) つに増やす操作と言い換えられるので、以下の問題が解ければ良いことになります。

  • \(\mathbb{F}_3\) 上の \(K+1\) 次元ベクトル \(\bm{v}_1, \bm{v}_2, \dots, \bm{v}_N\) がある。これらに適切に係数を割り振り、その和を \(\bm{0}\) にするような方法を考える。係数が \(0\) または \(2\) であるベクトルの番号の最大値を最小化せよ。(すべての係数が \(1\) の場合は、ベクトルの番号の最大値は \(0\) とみなす。)

これは、最初にすべての係数から \(1\) を引いておくことにすると、 \(\bm{u}:=-\sum_i \bm{v}_i\) を用いて次のように言い換えられます。

  • \(\mathbb{F}_3\) 上の \(K+1\) 次元ベクトル \(\bm{v}_1, \bm{v}_2, \dots, \bm{v}_N\) がある。これらに適切に係数を割り振り、その和を \(\bm{u}\) にするような方法を考える。係数が \(1\) または \(2\) であるベクトルの番号の最大値を最小化せよ。( \(\bm{u}=\bm{0}\) なら \(0\) を出力。)

これは、\(\{\bm{v}_1,\dots,\bm{v}_i\}\)\(\bm{u}\) を生成するような \(i\) の最小値です。よって、木を番号 \(i\) が小さい方から順番に見て、\(\{\bm{v}_1,\dots,\bm{v}_i\}\) の基底のみを記録しながら、それが \(\bm{u}\) を生成するかを判定するという解法が考えられます。

この解法の計算回数を調べます。掃き出し法を行うことにすると、各 \(i\) における計算回数は、その時点での \(\bm{v}_1,\dots,\bm{v}_{i-1}\) の基底の個数を \(x\) として、 \((x+1)K\) 回程度です。\(i\) への操作の直前には、基底の個数が \(\min(i-1,K)\) 個以下となるので、\(N \leq K\) の時は \(\sum_{i=1}^N iK=O(N^2K)\) 程度の計算回数となります。また、\(N \geq K\) の時は、基底の個数が常に \(K\) 以下となることから、\(\sum_{i=1}^N K^2=O(NK^2)\) 程度の計算回数となります。以上より、時間計算量は \(O(NK\min(N,K))\) であり、\(NK\) が一定の下では \(O(NK\sqrt{NK})\) となるので、制約の下で十分高速にこの問題を解くことができます。

投稿日時:
最終更新: