解説
この問題を愚直に解こうとすると
- (X1,X2) の選び方: S−1 通り
- i を 1 か 2 から選ぶ操作を N 回: 2N 通り
の O(S2N) 通りを試す必要があります。
実行時間制限の 2 秒では 109 回程度の演算しかできないため、S×2N≈1018×214≈1022 回の演算は TLE となります。
そのため、工夫して時間計算量を削減しましょう。
操作順を変える
具体例として入力例 1 の操作列を考えます。
(3,5)i=1(10,5)i=2(10,16)i=1(5,16)
i=1 を選んだ操作と i=2 を選んだ操作は独立です。つまり、i=1 を選んだ操作と i=2 を選んだ操作の順番を入れ替えても最終的な値は変わりません。
よって、入力例 1 の操作列は次のように並び替えられます。
(3,5)i=1(10,5)i=1(5,5)i=2(5,16)
なので、i=1 を選んだ操作をしたあとに i=2 を選んだ操作をするとして良いです。
逆操作を考える
さらに計算量を削減するため、入力で与えられる (Y1,Y2) から X1+X2=S となるような (X1,X2) を探す方法を考えます。
整数 A に対して整数 B を次のように定義します。
- A が偶数なら B=2A
- A が奇数なら B=3A+1
この B は A=Xi のときに、操作手順 2 を行った後の Xi の値です。
A を B を用いて表します。
- A=2B
- A=(B−1)/3
- (B−1) が 3 で割り切れる
- (B−1)/3 が奇数
よって B となりうるのは A=2B と A=(B−1)/3 に限られることがわかります。
したがって、(Y1,Y2) から逆操作を N 回繰り返して、X1+X2=S となるような (X1,X2) のペアがあるかを調べれば良いです。
実装方法
以上の考察を元にすると、
- A=2B か A=(B−1)/3 をどちらに行うのかの 2N 通り
- 逆操作を Y1 に何度行うのかの N+1 通り
の計 O(N2N) 通りについて、それぞれ N 回の逆操作を実際に行って X1+X2=S となるかを判定することにより、O(N22N) で解くことができます。
これは再帰関数や bit 全探索によって実装できます。
実装例
再帰関数を用いた実装例 (C)
再帰関数を用いた実装例 (C++)
再帰関数を用いた実装例 (Python)
bit 全探索を用いた実装例 (C)
bit 全探索を用いた実装例 (C++)
bit 全探索を用いた実装例 (Python)