1. 程式人生 > >【Atcoder diverta2019 E】XOR Partitioning

【Atcoder diverta2019 E】XOR Partitioning

判斷 開始 vector 們的 div 需要 tle 數量 就是

題意:給一個序列,然後問有多少種方法能夠把這個序列分成多塊使得每一塊的亦或和都相同。

思路:首先這種亦或和相同的題肯定要做前綴亦或和辣~

然後我們可以看如果我們選了一些分界點,會發生什麽。

首先每一個分界點肯定要麽是\(0\)要麽是\(x\),即每一段的亦或和。

並且\(0\)\(x\)總是間隔出現的。

所以我們就可以想到\(dp\)的狀態:

\(dp(i)\)表示現在要求以\(i\)這位為結束的答案。

那麽我們轉移的時候找到所有在它之前的與他前綴亦或和相同的數們,加上它們的\(dp\)值乘上它們中間\(0\)的個數。

那麽這樣是\(O(n^2)\)的,肯定TLE。

下面考慮優化。

首先我們覺得肯定可以把每一個不同的亦或前綴和單獨\(dp\)


(因為每一個數的\(dp\)值不會轉移到另外一個上面

那麽就可以通過維護之前所有的\(dp\)值的和以及之前所有\(dp\)值對當前\(dp\)值的貢獻來做到。

當前的\(dp\)值就是之前所有的貢獻\(+1\)

然後這個\(dp\)值加入所有\(dp\)值的和,以及所有\(dp\)值的貢獻在走過一個或幾個\(0\)所分割的段時需要加上經過的\(0\)的數量。

這樣就可以了。在\(dp\)的時候註意判斷最後一個亦或前綴和(即所有數的亦或值)不是\(0\)的情況,這代表了我們必須取最後一個的\(dp\)值。(我就在這裏栽了好久

KrK:
首先把每個數出現位置放到vector中,然後開始dp:
考慮dp[i]表示到了第i位置,現在末尾就是a[i]的答案。
那麽我們轉移的時候是找到所有a[j]=a[i]的j,dp[i]加上dp[j]*(ij中間的0個數)。
所以我們就可以通過(現在的0個數)-(j時前面的0個數)來表示ij中間的0個數。
所以設add1、add2兩個數組表示所有可以轉移到i的dp值的和,所有可以轉移到i的dp值乘上當時0的個數的和。
這樣用add1乘上現在0的個數減去add2就是dp值了。
最後需要特判一下a[n]=0的情況,因為那時候只可以用最後一個位置的dp值,並且不能加上0的2^(n-1)的答案。

yutaka:
吐槽:這個變量名為什麽要叫odd和even啊。。。
其實只是我們對於每一個數來處理dp,
然後就用odd表示所有dp值的和,even表示所有dp值乘上會給當前這個數造成的貢獻的和。
那麽最後就是答案如果a[n]=0就加上odd,否則加上even辣。
其實和KrK差不太多吧。

【Atcoder diverta2019 E】XOR Partitioning