分割数のいい感じの問題!
問題概要
長さ の数列
killA, killB が与えられる。この 2 つの広義単調減少である。
次の条件を満たす長さ の数列
deathA, deathB の組の個数を 1000000007 で割ったあまりを求めよ。
killAの総和 =deathBの総和killBの総和 =deathAの総和killA[i]=killA[j]かつならば、
deathA[i]deathA[i]であるkillB[i]=killB[j]かつならば、
deathB[i]deathB[i]である
制約
killA,killBの要素の総和は以下
考えたこと
分割数が活躍する問題だ。
分割数は、「自然数 を
個の 0 以上の整数の和で表す方法の数」のことであり、
と表すことにする。。ただし、和として表すときの順序は問わない。
たとえば、 のときは
というように 5 通りの方法があるので、 である。
分割数は、次の漸化式で求められる。
この漸化式の導出方法としては、自然数 を
個の 0 以上の整数の和で表す方法のうち、
を含むものと含まないものに場合分けして考える。
を含むとき、その
を除去しても方法の数は変化しないので、
を
個の整数の和として表す方法の個数に等しい。よって、
通り。
を含まないとき、和が
となる
個の各整数から
ずつ引くことで、「
を
個の
以上の整数の和として表す方法」に帰着される。よって、
通り。
これらをまとめて、上記の漸化式が得られる。
今回の問題
今回の問題では、killA, killB の値が等しい区間の扱いが若干面倒である。killA, killB が等しい区間はまとめて処理したい。
そこで、数列 を次のように、整数値のペアの列とする。
= (
killA において 番目に大きい数
,
killA におけるその数の個数 )
このとき、deathA の個数を求めるのは次の DP でできる。なお、deathB の方も同様である。
dp[i][j] ← deathA の先頭から 個までについて、総和が
となるようなものの個数
DP の遷移は次のように書ける。分割数が登場する。
dp[i+1][j+k] +=
dp[i][j]
計算量は = (
killA や killB の総和としてあり得る最大値) として、
- 分割数を前処理する:
- DP する:
となる。