分割数のいい感じの問題!
問題概要
長さ の数列 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 する:
となる。