ABC464 F - Random Vault Heist
ランダム強盗
考え方
まず、$N \leq 20$ の場合の $O(2^N)$ 解法を考える。
例として、金庫が $3$ 個で、中身が $2$ と $3$ と $4$、目標金額が $7$ である場合を考える。
金庫を開ける順序は $6$ 通りあり、以下の寄与を合計して、期待値は $25/3$ となる。
| 開ける順序 | 期待値の寄与 |
|---|---|
| $(2,3,4)$ | $(2+3+4)/6 = 3/2$ |
| $(2,4,3)$ | $(2+4+3)/6 = 3/2$ |
| $(3,2,4)$ | $(3+2+4)/6 = 3/2$ |
| $(3,4)$ | $(3+4)/6 = 7/6$ |
| $(4,2,3)$ | $(4+2+3)/6 = 3/2$ |
| $(4,3)$ | $(4+3)/6 = 7/6$ |
これを、何個目に開ける金庫からの寄与かで和の取り方を作り直す。
| 何個目の金庫か | 期待値の寄与 |
|---|---|
| $1$ 個目の金庫 | $(2+2+3+3+4+4)/6 = 3$ |
| $2$ 個目の金庫 | $(3+4+2+4+2+3)/6 = 3$ |
| $3$ 個目の金庫 | $(4+3+4+3)/6 = 7/3$ |
さらに、それぞれの中で、直前までにどの金庫を開けたのかで分解する。
| 何個目の金庫か | 直前までに開けた金庫 | 期待値の寄与 |
|---|---|---|
| $1$ 個目の金庫 | $( )$ | $(2+3+4)/3 = 3$ |
| $2$ 個目の金庫 | $(2)$ | $(3+4)/6 = 7/6$ |
| $2$ 個目の金庫 | $(3)$ | $(2+4)/6 = 1$ |
| $2$ 個目の金庫 | $(4)$ | $(2+3)/6 = 5/6$ |
| $3$ 個目の金庫 | $(2,3)$ | $4/3 = 4/3$ |
| $3$ 個目の金庫 | $(2,4)$ | $3/3 = 1$ |
それぞれの分子の和は、残っている金庫の総額である。
つまり、全金庫の総額から、既に開けた金庫の総額を引いて求められる。
分母は、「事前に開けたものがそうなった上で、次の $1$ 個で残りのそれぞれの金庫を開ける確率」の分母。
つまり、今回の期待値は、以下で求まる。
$$
\frac{9-0}{{}_3\mathrm{C}_0 \times 3}+\frac{9-2}{{}_3\mathrm{C}_1 \times 2}+\frac{9-3}{{}_3\mathrm{C}_1 \times 2}+\frac{9-4}{{}_3\mathrm{C}_1 \times 2}+\frac{9-5}{{}_3\mathrm{C}_2 \times 1}+\frac{9-6}{{}_3\mathrm{C}_2 \times 1}=\frac{25}{3}
$$
これは、各項ごとに、選んだ金庫の組の個数と合計額のみから $O(1)$ で高速に計算できる。
(逆数に毎回繰り返し二乗法を用いなくて済むように、階乗や各種逆数を事前計算しておく)
つまり、以下のようなデータを高速に構築できれば、$7$ 未満のデータだけ拾うことで $O(2^N)$ で解ける。
| 選んだ金庫の個数 | 合計額 |
|---|---|
| $0$ 個 | $0$ |
| $1$ 個 | $2, 3, 4$ |
| $2$ 個 | $5, 6, 7$ |
| $3$ 個 | $9$ |
このデータの構築は、以下の方法を用いる。
最初に、このような形のデータを用意する。
| 選んだ金庫の個数 | 合計額 |
|---|---|
| $0$ 個 | $0$ |
| $1$ 個 | |
| $2$ 個 | |
| $3$ 個 |
ここに、金額 $2$ の金庫の影響を処理する。
つまり、すべてのデータについて、合計額に $2$ を加えて、個数が $1$ 大きいところに付け加える。
| 選んだ金庫の個数 | 合計額 |
|---|---|
| $0$ 個 | $0$ |
| $1$ 個 | $2$ |
| $2$ 個 | |
| $3$ 個 |
次に、金額 $3$ の金庫の影響を処理する。
方法は同様だが、$1$ 個のところはマージソートの要領で昇順に保っておく。
(これは、$N \leq 20$ のときには特に意味がないが、$N \leq 40$ に対応するときに役に立つ)
| 選んだ金庫の個数 | 合計額 |
|---|---|
| $0$ 個 | $0$ |
| $1$ 個 | $2, 3$ |
| $2$ 個 | $5$ |
| $3$ 個 |
最後に金額 $4$ の金庫の影響を処理すれば、前述のデータが $O(2^N)$ で構築できる。
あとは、$1$ つずつ分数計算をすればよい。
以上が、$N \leq 20$ の場合に $O(2^N)$ で解く方法である。
さて、ここまでは前座で、この問題はここからが本番である。
$N \leq 40$ の場合には $O(2^N)$ では間に合わず、$O(N 2^{N/2})$ くらいでどうにかしなければならない。
まず、$2^40$ 通りの列挙は絶対に無理なので、半分全列挙で前後半それぞれの $2^20$ 通りずつ全列挙する。
そして、前半から $i$ 個、後半から $j$ 個とるパターンごとにまとめて処理していく。
これらの寄与を計算するときの分母は、${}_N\mathrm{C}_{i+j} \times (N-i-j)$ でよい。
分子側は前半から $i$ 個とるデータの配列と、後半から $j$ 個とるデータの配列を見て求める。
前者の値と後者の値の和が $X$ 未満になるような全組について、「全総額-その値」の総和を出せばよい。
これは、後者のインデックスを進めながら前者のインデックスを戻すツーポインタ法で求められる。
前者側の累積和も事前に取っておけば、両配列の長さの和に比例する時間で求まる。
これを $i$ と $j$ 全ての組について実行して全ての和をとればよい。
半分全列挙のために $A$ を分けたときに、左側に $l$ 個、右側に $r$ 個あったとする。
すると、ツーポインタ法の二重ループ全体で $O(l2^r+r2^l)$ 回かかる。
これは $l$ と $r$ を均等に分けたら $O(N 2^{N/2})$。
他にこれより計算量が膨らむところはないので、全体の計算量も $O(N 2^{N/2})$。
これで $N \leq 40$ の場合にも解ける。
入力例3での動作
入力例 $1$ があまり動作説明に適さないので、入力例 $3$ で例を示す。
入力を受け取る。
n: 11
x: 60
a: {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31}
半分全列挙をするため、$A$ を前半と後半に分ける。
前半: {2, 3, 5, 7, 11}
後半: {13, 17, 19, 23, 29, 31}
まず、前半について、選ぶ個数ごとに部分集合和を昇順で列挙する。
| 選ぶ個数 | 前半の部分集合和 |
|---|---|
| $0$ | $0$ |
| $1$ | $2,3,5,7,11$ |
| $2$ | $5,7,8,9,10,12,13,14,16,18$ |
| $3$ | $10,12,14,15,16,18,19,20,21,23$ |
| $4$ | $17,21,23,25,26$ |
| $5$ | $28$ |
後半についても同様に列挙する。
以下では、前半から $2$ 個、後半から $2$ 個を既に開けた場合を例として追う。
後半から $2$ 個選んだ部分集合和は次の通りである。
30, 32, 36, 36, 40, 42, 42, 44, 46, 48, 48, 50, 52, 54, 60
前半から $2$ 個選んだ部分集合和と、その累積和は次のようになる。
部分集合和: {5, 7, 8, 9, 10, 12, 13, 14, 16, 18}
累積和: {0, 5, 12, 20, 29, 39, 51, 64, 78, 94, 112}
全金庫の総額は $160$ である。
後半側の部分集合和を $k$ とする。
前半側の部分集合和が $60-k$ 未満のものだけが、既に盗んだ合計が $X=60$ 未満という条件を満たす。
例えば、いくつかの $k$ について計算すると次のようになる。
| 後半側 $k$ | 上限 $60-k$ | 前半側の個数 | 前半側の合計 | 分子部分 |
|---|---|---|---|---|
| $30$ | $30$ | $10$ | $112$ | $(160-30)\times10-112=1188$ |
| $42$ | $18$ | $9$ | $94$ | $(160-42)\times9-94=968$ |
| $60$ | $0$ | $0$ | $0$ | $0$ |
後半から $2$ 個選ぶ場合について、全て同様に計算する。
この組み合わせでの分子部分の合計は $10978$ となる。
前半から $2$ 個、後半から $2$ 個の合計 $4$ 個を既に開けている。
その $4$ 個の集合が最初に開けられる確率は $1/{}_{11}\mathrm{C}_4$ である。
次の金庫は残り $7$ 個から一様ランダムに選ばれる。
したがって、この場合の期待値への寄与は次の値である。
$$
10978 \times \frac{1}{{}_{11}\mathrm{C}_4} \times \frac{1}{7}
$$
前半から選ぶ個数と、後半から選ぶ個数の全ての組み合わせについて同じ処理を行う。
それぞれの寄与を剰余類環上で加算すると、最終的な答えは $525950964$ となる。
注意点
A_i、X、部分集合の合計値は、int 型からはみ出る。
long long 型を用いること。
sum1 は部分集合和の総和を持つため、そのまま加算すると long long 型からもはみ出る。
各加算ごとに $998244353$ で割った余りを取ること。
答えは $998244353$ で割った余りを要求されているので、剰余類環の考えに従って処理する。
何か足し算や掛け算をするたびに結果を % 998244353 する。
割り算は通常 $998244353-2$ 乗したものを掛けるが、それでは計算量が増えてしまう。
階乗の事前計算で逆数も求めておき、繰り返し二乗法を毎回しなくて済むように高速化しておくこと。
別解
特になし。