題意
給定正整數 \(N, M, K\) 和一個非負整數序列 \(A = (A_1, A_2, \dots, A_N)\)。
對於一個非空的序列 \(B = (B_1, B_2, \dots, B_{|B|})\),我們定義它的得分為:
- 若 \(|B|\) 為 \(M\) 的倍數:\((B_1 \oplus B_2 \oplus \dots \oplus B_{|B|})^K\)。
- 否則為 \(0\)。
這裡 \(\oplus\) 運算表示按位異或。
找到序列 \(A\) 的 \(2^N - 1\) 個非空子序列的得分之和,對 \(998244353\) 取模。
首先考慮轉化這個 \(K\) 次方,發現對於異或和很難用組合方面的知識轉化,所以直接考慮對於每個 \(x\),求 \(f_x\) 表示有多少長度為 \(M\) 倍數的子序列異或和等於 \(x\)。總答案為 \(\sum\limits_{x} \left(f_x \times x^k\right)\),問題轉化為求出 \(f\) 陣列。
這個問題的形式很 \(\operatorname{FWT}\),更進一步,我們有 \(n\) 個冪級數 \(H_i\),第 \(i\) 個冪級數 \(\operatorname{FWT}\) 前只有 \(0\) 和 \(A_i\) 的位置有值,因為有 \(M\) 的限制,所以我們考慮把它的係數變成一個矩陣 \(Y\),因為 \(\operatorname{FWT}\) 是一個線性變換,所以係數是整數還是矩陣都沒有影響。
將每個 \(H_i\) \(\operatorname{FWT}\) 一遍後得到 \(H_i'\),將其點乘起來並 \(\operatorname{IFWT}\) 一遍後就得到了 \(f_i\) 了,時間複雜度 \(O(n V \log V)\),其中 \(V\) 是 \(A_i\) 的值域。
考慮最佳化上面這個做法,容易發現每個 \(H_i\) 中只有 \(A_i\) 和 \(0\) 的位置有值,分別是 \(Y\) 和 \(I\),其中 \(I\) 是單位矩陣。根據 \(\operatorname{xor}\) 運算的 \(\operatorname{FWT}\) 的性質,\(H_i' = \sum_j (-1)^{\operatorname{popcount}(i ~\&~ j)} H_j\),則可以發現 \(H_i'\) 只有兩種情況:\((I + Y)\) 或 \((I - Y)\)。所以最後點乘後得到的 \(f_i'\) 一定為 \((I + Y)^a(I - Y)^b\),且 \(a + b = N\)。
先用 \(O(NM)\) 的 \(dp\) 預處理出矩陣的值(其實根本不用推出這個矩陣),只需要記 \(dp_1[i][j]\) 和 \(dp_2[i][j]\),然後用下面的遞推式推導即可:
再推一個 \(G_i = \sum\limits_{j = 0}^{M - 1}dp_1[i][j] \times dp_2[N - i][(M - j) \bmod M]\),這樣得到了 \((I + Y)^i(I - Y)^{N - i}\) 的值了。
接下來考慮快速得到這個 \(a\),根據 \(\operatorname{FWT}\) 的性質,如果 \(\operatorname{popcount}(x ~\&~ y)\) 為偶數,那麼 \(y\) 就給 \(f_x\) 貢獻了一個 \((I + Y)\)。所以計算 \(f_x\) 的 \(a\),實際上是在計數有多少 \(A_i\) 使得 \(\operatorname{popcount}(A_i ~\&~ x)\) 為偶數。考慮使用 \(\operatorname{FWT}\) 加速這一過程,記 \(F_{i, j}\) 表示有多少 \(x\),使得 \(\operatorname{popcount}(i, x) \bmod 2 = j\),初始值 \(F_{x, 0} = cnt(x)\)(因為初始的時候相當於序列長度只有 \(1\)),其中 \(cnt(x) = \sum\limits_{i = 1}^N[x = A_i]\)。
基於 \(\operatorname{FWT}\) 蝴蝶變換時的性質,當兩邊進行合併時剛好有 \(1\) 位不同,所以有轉移(記 \(x = j + k, y = i + j + k\),其中 \(i, j, k\) 為蝴蝶變換時的三個下標):
最後將 \(f'_i \gets G_{F_{i, 0}}\) 即可,\(\operatorname{IFWT}\) 一遍就得到原來的 \(f_i\) 了,總時間複雜度 \(O(NM + V \log V)\)。
程式碼是賀的,就不放了。