給定 n≤50 個數 a_i (≤2^20),查詢有多少非空子集的異或和 > m。多測試用例。
dp[i][x] = 前 i 個數中,異或和為 x 的子集數。
轉移:
dp[i][x] = dp[i-1][x] + dp[i-1][x ^ a_i]
(不選 a_i + 選 a_i)。
只依賴上一行,用 dp[2][1<<20] 交替。
初始 dp[0][0] = 1(空集)。
const int MAXX = 1<<20;
long long dp[2][MAXX];
int main() {
int T; scanf("%d",&T);
while (T--) {
int n, m; scanf("%d%d",&n,&m);
memset(dp, 0, sizeof dp);
dp[0][0] = 1;
for (int i=1;i<=n;++i) {
int a; scanf("%d",&a);
int cur = i&1, pre = cur^1;
for (int x=0;x
時間 O(n * 2^20) ≈ 50 * 1e6 = 5e7,C++ 優化後約 0.5-1s。
空間 2 * 2^20 * 8B ≈ 16 MB。
int 存儲計數(模數題),或 long long 無模數。m 較大,可反向統計 ≤m 再用總數相減(總數 = 2^n - 1)。