Processing math: 100%

AtCoder Regular Contest 156 D問題メモ

D - Xor Sum 5

問題

  • 長さ N の数列 A=(A1,...,AN)
  • 長さ K、各要素 1XiN の数列 X=(X1,...,XK) に対し、f(X) を以下で定義する
    • f(X)=AX1+AX2+...+AXK
  • X としてあり得る数列は NK 通りあるが、それら全てについての f(X) の総XORを求めよ
  • 1N1000
  • 0Ai1000
  • 1K1012

解法

考慮すべき X の個数がとんでもない数になりそうだが、実は多くはXORで打ち消しあって消える。
合計が同じになる、要素を並び替えただけの2つの X 同士は打ち消しあうため、考慮しなくてよい。

たとえば K=11 個から、A13 個、A34 個、A54 個選ぶような X の個数は、 多項係数 11!3!×4!×4! で求められる。
これが偶数になるような選び方は考慮しなくてよいことになる。
また、奇数の時も打ち消しあって残った1個のみ考慮すればよい。

では、奇数になるのはどんなとき?
これは、Lucasの定理を使える。

特にmod2、nCr の偶奇を知りたいときは、以下が成り立つ。

  • nCr は奇数 ⇔ n&r=r 、つまり r を2進数表記したときに立っているbitは、n でも全て立っている

今回の場合もこれを連鎖的に適用すると、以下が成り立つ。

  • K!r1!r2!...rm! が奇数
  • r1,r2,...,rm が、どの2つもどのbitも重複していない(ri&rj=0)、かつ総和が K

これを言い換えると(なかなか直感的には言い換えるのが難しく思うが)、
K の2進数表記で立っているbitごとに、A1AN のどれかから選んでbitshiftして足し合わせる」ような操作で作られる数が、並べ替えの個数が奇数となるような X に対する f(X) となる。

K = 1011            ※K,Aiは2進数表記
A = (10, 11, 101)

    1の位    10の位      1000の位       f(X)   加算するAiの内訳
o-- + 10 --- + 10*0 --- + 10*000   →  10110   10を11個
|       |          |--- + 11*000   →  11110   10を 3個、 11を 8個
|       |          `--- +101*000   → 101110   10を 3個、101を 8個
|       |--- + 11*0 --- + 10*000   →  11000   10を 9個、 11を 2個
|       |          |--- + 11*000   → 100000   10を 1個、 11を10個
|       |          `--- +101*000   → 110000   10を 1個、 11を 2個、101を 8個
|       `--- +101*0 --- ...
|                  |--- ...
|-- + 11 --- ...
`-- +101 --- ...
                                      ~~~~~~ 答えは、ここに来る全f(X)のXOR

答えを求める際には、この樹形図を縦に見て、下の桁から確定させていく。

1の位で答えの下1桁を求めたら、10や1000の位ではもう変化しないので、確定する。

  • Ai の下1桁のXORが1」かつ「N が奇数」の場合に限り、答えの下1桁は1となる。
    • この後、樹形図に従い各枝はそれぞれ等しく N の(残り枝分かれ回数)乗倍されるが、そもそもXORが0なら、何倍しても0
    • N が偶数の場合、最後の枝(上例では1000の位)以外は、「N の○乗倍」が偶数となり、打ち消し合うため

次、10の位を考慮するにあたり、繰り上がりが発生する。
「10からは1」「11からは1」「101からは10」繰り上がるが、「1」繰り上がる2つに関しては、この後の樹形図が同じため打ち消し合う。
したがって、「10」のみが残る。繰り上がる数も、奇数個繰り上がるもののみを持っておけばよい。

10の位では、繰り上がってきた数それぞれに対して、各 Ai を加算した集合(上例では100,101,111)で 同様に下1桁のXORを計算し、答えに反映する。

100の位では、K でbitが立っていないため、(Ai は加算せず)繰り上がってきた数の集合のままで下1桁のXORを計算する。
K で立っているbitを予め調べ、10の位とまとめて求めてもよい)

1000の位でも同様に、各繰り上がった数に各 Ai を足す。
最後については下1桁でなく、Ai 加算後の集合のそのままの値のXORを求め、bitshiftして答えに加算する。
最後は、N が偶数でも加算してよい。
これで最終的な答えとなる。

各桁で繰り上がる数の種類数の上限は、Amax2500
それぞれに N 個の Ai の加算を試す、ということを最大 O(logK) 回おこなうため、計算量は O(NAmaxlogK)

Python3

programming_algorithm/contest_history/atcoder/2023/0218_arc156.txt · 最終更新: 2024/05/14 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0