Keycards(カードキー) - joi2011-day2 解説

筆者: qnighy

「穴」の集合Nの冪集合である「キーカード」の集合2^Nがあるとき、「キーカードの組み合わせ」の集合2^2^Nのうちその要素の積集合の個数がKであるようなものの数え上げである。

部分点解法

省略

O(NlogN)解法

(logNは逆元を求めるためのものであり、他の本質的な部分はO(N)である。)

問題の整理

まず、この問題では、「1枚も受け取らなかった」場合を数えないことにしている。これは数学的には対称性が悪く、扱いづらいので、この場合は「全ての穴が空いていた」状態として数えることにする。(すなわち、N=Kの場合は、最後に1を引けばよい。)

K個の穴が共通して開いている場合を考えたいが、これをまず開いている穴の組み合わせによって分類してみよう。

すると、開いている穴の組み合わせはnCkあるので、開いている穴の組み合わせを固定した場合の数を求めてからnCk倍すれば答えが得られることがわかる。

残りn-k個の穴についての考察

ここで、残りr=n-k個の穴(開いていてはいけない穴)に注目してみよう。

ここではr=3とし、これらの穴をA,B,Cとおく。

求めたい場合は、[Aが開いていない場合]∩[Bが開いていない場合]∩[Cが開いていない場合]の個数である。

これは、包除原理より、

[すべての場合]-[Aが開いている場合]-[Bが開いている場合]-[Cが開いている場合][AとBが開いている場合][BとCが開いている場合]+[CとAが開いている場合]-[AもBもCも開いている場合]

で計算できる。

包除原理を適用した式の計算方法

i個の穴が開いているカードキーは2^(r-i)枚あるので、i個の穴が開いているようなカードキーの組み合わせは2^2^(r-i)個ある。

同じ個数の穴が開いている場合を纏めて考えると、

Σ(i←0…r) rCi × 2^2^(r-i) × (-1)^(r-i)

を求めればいいことがわかる。

コンビネーションの計算

ここで、コンビネーションを上手に計算することが必要になる。

この場合、コンビネーションを線形で計算する必要があるので、

の漸化式を用いてrCxを予め全て計算しておくのがよい。

逆元の計算

これを求めるためにmod pにおける逆元(invmod)を求めることが必要になるが、これには

の2通りがよく知られており、前者は一回log(p)、後者は一回log(a)で求めることができる。

以上の方法を実装することで満点が獲得できる。