ツバサの備忘録

主に備忘録代わりに精進記録を載せていくつもりです。

ABC129 E - Sum Equals Xor

問題
提出コード

解法

制約を見ると明らかに桁DPのような匂いがするので桁DPをしました。
a,bの上からi桁目をa_{i},b_{i}とします。
(a_{i},b_{i}) = (1,1)となるiが存在した場合、a+bをすると繰り上がりが発生するので、a+b \neq a \ xor \ bとなります。逆に、それ以外の(0,0), (0,1), (1,0) はどれを使用してても問題の条件を満たします。
ということで、(0,0), (0,1), (1,0)のみを選択してa+ b \leqq Lとなる(a,b)のペアの個数を求めることができればよいです。
dp[i][j]という配列を用意します。添え字はそれぞれ次のことを表します。

  • i:今上から何桁目までの数字を決めたか

  • j:a+bL未満の数字であることが確定しているかどうか

つまり、
dp[i][1]は、上からi桁だけ数字を決めて、a,bどちらもL未満であるようなペア(a,b)の個数
dp[i][0]は、上からi桁だけ数字を決めて、a+b=Lとなっているようなペア(a,b)の個数
となります。
このようなことができるのは、上から数字を決めていったときに、その時点でa+b \lt Lが確定していれば、それより下の桁をいかなる数字にしても、a+b \lt Lであることが決まっているからです。 Lの上からi桁目をL_{i}として、L_{i}について場合分けをしつつ遷移を見ていきます。

  • L_{i}1のとき
    dp[i-1][j]からの遷移を考えます。
    j=0のときに、i桁目で(0,0), (0,1), (1,0)をそれぞれ選んだ場合どうなるか、を考えると、
    (0,0)を選んだ際はa+b \lt  Lが確定します。
    逆に、(0,1), (1,0)を選んだ際は、a+b =  Lとなります。
    ということで、まず
    dp[i][1] += dp[i-1][0]
    dp[i][0] += dp[i-1][0] \times 2
    が決まります。
    j=1のときに、i桁目で(0,0), (0,1), (1,0)をそれぞれ選んだ場合どうなるか、を考えると、
    (0,0), (0,1), (1,0)どれを選んでもa+b \lt  Lが確定しています。
    よって、
    dp[i][1] += dp[i-1][1] \times 3
    となります。
    遷移元がこれで全部になるので、結局遷移は
    dp[i][1] = dp[i-1][1] \times 3  + dp[i-1][0]
    dp[i][0] = dp[i-1][0] \times 2
    となります。

  • L_{i}0のとき
    同様にしてdp[i-1][j]からの遷移を考えます。
    j=0のときに、i桁目で(0,0), (0,1), (1,0)をそれぞれ選んだ場合どうなるか、を考えると、
    (0,0)を選んだ際でも、a+b = Lとなります。
    (0,1), (1,0)を選ぶことはできません。Lを超えてしまいます。
    ということで、まず遷移は
    dp[i][0] += dp[i-1][0]
    となります。 j=1のときはというと、
    (0,0), (0,1), (1,0)どれを選んでもa+b \lt  Lが確定しています。
    ということで、
    dp[i][1] += dp[i-1][1] \times 3
    となります。
    よって、
    dp[i][0] = dp[i-1][0]
    dp[i][1] = dp[i-1][1] \times 3
    となります。


あとは、この場合分けをもとに遷移を行っていけばよいです。
初期状態ですが、
(何も見ていない)  = (0桁目までを見終えた) 、とみなすことができ、L未満であることはもちろん確定していないので、dp[0][0] = 1となります。
答えは、dp[n][0] + dp[n][1]となります。

感想

逆に、DPでない方法を考えることができませんでした。
いろいろな方法を思いつけるようになりたいですね。