アルゴリズム忘備録

競技プログラミングとかデータ分析とか

AtCoder Regular Contest 066 D - Xor Sum

atcoder.jp

 

今更書くまでもない超有名問題だけどかなり手こずったのでメモ。基本的に xor系は和ととても相性が悪い。

 

問題の性質を考えると、 a \oplus b = u, a + b = v を満たすとき、常に  u \le v であるため、 v \le N だけ考えればよい。また、足し算の有名な言い換え a + b = a \oplus b + a \ and \ b * 2があります。これはつまり、abのbitごとの交換に関して不変です。つまり、abの各bitは(0, 0), (0, 1), (1, 1)の3通りだけ考えれば良いです。

  

 dp[i][s] を上からi ビット目まで見たときに、 s * 2^iだけNより小さい場合の組み合わせ数と定義します。このとき、sが2以上の場合は、i+1ビット目について、 s * 2^{i+1} \ge 4*2^i となるため、例え今見ているビットが (1,1)で、Nのビットが0だったとしても 2*2^i以上Nより小さいことは確定します。そのため、sは状態として0,1,2の3通りだけ見るdpを考えればよいです。

 

なぜこんなdpが思いつくかというと、足し算の繰り上がりによりNを超えるギリギリの線を覚えておく、みたいな感覚になります。ここがちょっと難しいですが繰り上がり系のdpが出てきたときにはこの感覚を覚えておきたいです。

 

dpの遷移としては、N[i]をNのiビット目(0または1)と定義すると、 dp[i][min(2, 2s + N[i] -(a[i] + b[i]) ] += dp[i][j] などとなります。

 

計算量は O(\log_2 N)