GAMEFREAK Programming Contest 2023 (AtCoder Beginner Contest 317) F,G問題メモ

GAMEFREAK Programming Contest 2023 (AtCoder Beginner Contest 317)

抽選でポストカードが貰える!

F - Nim

問題

  • 正整数 $N$ と、$A_1,A_2,A_3$ が与えられる
  • 以下の条件を全て満たす3数 $(X_1,X_2,X_3)$ の組の個数を $\mod{998244353}$ で求めよ
    • $1 \le X_i \le N$
    • $X_1$ は $A_1$ の倍数、$X_2$ は $A_2$ の倍数、$X_3$ は $A_3$ の倍数
    • $X_1 \oplus X_2 \oplus X_3=0$($\oplus$:排他的論理和)
  • $1 \le N \le 10^{18}$
  • $1 \le A_i \le 10$

解法

3数の排他的論理和が0なので、2進数で表したときに全ての桁についてbitが「2数でだけ立ってる」か「どれも立ってない」かである。

$A_i$ の制約が小さいので、あまりを持った桁DPができる。
3数同時にあまりを管理しても、$O(\log{N} A_{max}^3)$ で、$6 \times 10^4$ 程度に収まる。
次の桁にbitを3つ中2つだけ立てた場合、どれにも立てなかった場合、に遷移していき、最終的にあまりが全て0のパターン数が答え、という解法が取れそう。

$N$ 以下であることが求められるので、よくある桁DPなら

  • 上の桁からDPして、$N$ 未満であることが確定したもののパターン数を管理する
  • $N$ ちょうどのものは別途管理しておき、未満になることが確定した時点で追加する

みたいな方法を取るが今回は3数同時に面倒を見る必要があり、どれか1個だけが $N$ ちょうどとかいう場合も考慮するので、 $N$ ちょうども状態の中に混ぜ込む必要がある。

$N$ を2進数で表して上から $k$ 桁を取ったものを $f(k)$ とするとして、

(例)N = 43 = 101011(2)  ⇒  f(4) = 1010(2) = 10

以下のDPを定義する。

  • $DP[i,j,k,l]=$ 上から $i$ 桁まで見て、
    • $X_1$ が以下に当てはまり、
      • $0 \le j \lt A_1$ のとき、「$X_1$ は $f(N,i)$ 未満であり、$A_1$ で割ったあまりが $j$」
      • $j=A_1$ のとき、「$X_1$ は $f(N,i)$ と一致」
    • $X_2$ と $k$、$X_3$ と $l$ についても同様の関係性であり、
    • 3数のXORが0であるような $(X_1,X_2,X_3)$ の個数

$DP[0,A_1,A_2,A_3]=1$ からはじめて、 $N$ を超えないように、また $N$ ちょうどの状態に注意しながら、 3数のうち2個にビットを立てるか、どれにも立てないかでパターンを遷移させていく。

最終的に $DP[N,0,0,0]$ が答えだが、$N$ 自身が $A_1$ で割りきれる場合、$DP[N,A_1,0,0]$ も答えに加算する。
(もし $A_2,A_3$ も割り切れるなら、その組み合わせだけ参照箇所が増える)

最後に、答えには $X_i=0$ の場合も含まれてしまっている。1以上で無ければいけないので、これを除外する。

  • $X_1$ のみが0の場合、XORが0となるためには、$X_2,X_3$ は一致する → 余分なのは $\dfrac{N}{A_2,A_3のLCM}$ 個含まれる
    • $X_2,X_3$ のみが0の場合も同様
  • 全て0の場合が1個含まれる

以上で答えとなる。

Python3

G - Rearranging

問題

  • $N \times M$ のグリッド状に、$1~N$ の数字が $M$ 個ずつ配置されている盤面が与えられる
  • 数字は、同じ行の中でなら自由に並べ替えられる
  • 全ての列を「$1~N$ の数字が1つずつある」状態にできるか判定し、可能ならその一例を示せ
  • $1 \le N,M \le 100$

解法

全てを一度に決めようとすると上手くいかない。

実は、「$1~N$ の数字が $M$ 個ずつ配置されている」という条件を満たしていれば必ず可能であり、 その証明があれば、1列ずつ貪欲に決めていってもいい、という考え方となる。
(入力サンプルにも可能な例しか無かった時点で少し怪しかったね)

いま、一番左端の1列だけをとりあえず決めるとする。
どうやっても $1~N$ を揃えるのは不可能というのはどんな状態か?

二部マッチングにおけるホールの定理を利用すれば、

  • ある行の集合 $R$ に存在する数の種類数が、その集合のサイズより少ない

場合に不可能であり、そうでなければ何らかの完全マッチングは存在する、ということになる。

→ 3 3 3 3 5    4行に存在する数の種類が、あわせても3種類しかない
→ 3 3 5 5 6    みたいな行の集合がある場合に不可能となる
   o o o o o
→ 3 3 3 6 6
→ 5 5 6 6 6

だが、これは少し考えると、数のどれかが $M$ 個より多く存在していないと不可能なので、あり得ない。

よって、左端の列に $1~N$ は必ず揃えることができ、1つ列が減った状態に帰結できる。
1つ列が減った状態も、$N$ 行 $m$ 列に対して「$1~N$ が $m$ 個ずつ」という条件は満たされているので、 同じ理屈により再帰的に完全マッチングが存在することが証明できる。

完全マッチングは最大流で求められる。
$N,M$ の制約が小さいので、各行に残っている数を管理しながら $M$ 回、グラフ構築から最大流を流しても十分間に合う。

Python3

programming_algorithm/contest_history/atcoder/2023/0826_abc317.txt · 最終更新: 2023/08/31 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0