XorCards
高斯消元 #xor
考虑拆分限制分别算,对于一个 \(5=(101)_2\) 的限制,它等价于满足 \(0xx\) 和 \(100\) 的方案数的和
及将一个前缀的 \(1\) 转为 \(0\) ,保证这个 \(1\) 前面的字符全部相等,剩下的部分任取
然后就可以得到一些 \(xor\) 方程组,然后只要求这个方程组的自由元个数 \(free\)
当前的贡献为 \(2^{free}\)
// Author: xiaruize
const int INF = 0x3f3f3f3f3f3f3f3f;
const int MOD = 1000000007;
const int N = 65 + 10;
int n;
int a[N];
int lim;
bitset<65> bt[N];
int guass(int n, int m)
{
int cnt = 0;
int r, c;
for (r = 1, c = 1; r <= n && c <= m; r++, c++)
{
int p = r;
while (p <= n && !bt[p][c])
p++;
if (p > n)
{
r--;
cnt++;
continue;
}
swap(bt[r], bt[p]);
rep(j, 1, n)
{
if (j == r || !bt[j][c])
continue;
bt[j] ^= bt[r];
}
}
bool fl = false;
// debug(r);
rep(i, r, n) fl |= bt[i][m + 1];
// debug(bt);
// rep(i, 1, n) cerr << bt[i][m + 1] << ' ';
if (fl)
return -1;
return cnt;
}
void solve()
{
cin >> n;
int m = 0;
rep(i, 1, n)
{
cin >> a[i];
}
cin >> lim;
// m = max(m, __lg(lim));
int res = 0;
per(i, 60, 0)
{
// debug(i);
if (!((lim >> i) & 1))
continue;
int cur = (lim >> i) - 1;
if (cur < 0)
continue;
rep(i, 1, 61) bt[i].reset();
per(k, 60, i)
{
bt[60 - k + 1][n + 1] = ((cur >> (k - i)) & 1);
rep(j, 1, n)
{
if ((a[j] >> k) & 1)
bt[60 - k + 1][j] = 1;
}
}
int fr = guass(60 - i + 1, n);
debug(i, cur, fr);
if (fr >= 0)
res += (1ll << fr);
}
int cur = lim;
rep(i, 1, 61) bt[i].reset();
per(k, 60, 0)
{
bt[60 - k + 1][n + 1] = ((cur >> k) & 1);
rep(j, 1, n)
{
if ((a[j] >> k) & 1)
bt[60 - k + 1][j] = 1;
}
}
int fr = guass(61, n);
// debug(i, cur, fr);
if (fr >= 0)
res += (1ll << fr);
cout << res << endl;
}
#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif
signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int testcase = 1;
// cin >> testcase;
while (testcase--)
solve();
#ifndef ONLINE_JUDGE
cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
return 0;
}