AT_abc283_g [ABC283G] Partial Xor Enumeration 题解

题目传送门

前置知识

线性基

解法

考虑线性基。

因为有可空子序列也参与运算,所以第 \(1\) 小的数是 \(0\);但线性基中是不允许有异或和为 \(0\) 的存在,故线性空间内第 \(k-1\) 小的数就是所求的第 \(k\) 小的数。

令每一个二进制位仅在它这一位的基底上出现,其他位上的基底直接异或掉。

\(k\) 二进制分组后取每一位的基底异或起来即可。

观察到 \(r-l \le 2 \times 10^{5}\),暴力处理每一组询问即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
ll d[70];
vector<ll>dd;
void insert(ll x)
{
    for(ll i=60;i>=0;i--)
    {
        if((x>>i)&1)
        {
            if(d[i]==0)
            {
                d[i]=x;
                break;
            }
            x^=d[i];
        }
    }
}
ll ask(ll x)
{
    x--;
    ll ans=0;
    for(ll i=0;i<dd.size();i++)
    {
        if((x>>i)&1)
        {
            ans^=dd[i];
        }
    }
    return ans;
}
int main()
{
    ll n,l,r,x,i,j;
    cin>>n>>l>>r;
    for(i=1;i<=n;i++)
    {
        cin>>x;
        insert(x);
    }
    for(i=0;i<=60;i++)
    {
        if(d[i]!=0)
        {
            for(j=0;j<=i-1;j++)
            {
                if((d[i]>>j)&1)
                {
                    d[i]^=d[j];
                }
            }
            dd.push_back(d[i]);
        }
    }
    for(i=l;i<=r;i++)
    {
        cout<<ask(i)<<" ";
    }
    return 0;
}

后记

多倍经验: HDU3949 XOR

posted @ 2024-10-10 16:04  hzoi_Shadow  阅读(18)  评论(2编辑  收藏  举报
扩大
缩小