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;
}
posted @ 2024-04-07 20:46  xiaruize  阅读(6)  评论(0)    收藏  举报