牛客17968 xor序列(線性基學習)

鏈接

https://ac.nowcoder.com/acm/problem/17968

線性基

線性基的概念

在線性代數中有基的概念,我在這裏援引百度百科
在這裏插入圖片描述
異或其實就是模加法,FF就取{0,1}\{0,1\},每個整數都可以看作一個向量,VV就取輸入的整數集合誘導出的向量集合。線性基本質上是一組基向量,只不過形式上我是用整數表示的。

線性基的構造方法

bkb_k表示最高位的11在第kk位的向量(整數)
對於一個新加入的數pp(其實就是一個向量),從最高位開始掃,發現當前位(第kk位)等於11時,如果bkb_k沒有,那就令bkpb_k\leftarrow p,並退出;否則pp^=bk=b_k,然後繼續下一位
如果要查詢某個數能通過基中的整數異或出來,可以貪心地從高位到低位填

代碼

#include <bits/stdc++.h>
#define maxn 100010
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;
struct LinearBasis
{
    ll b[70];
    void clear(){cl(b);}
    void build(ll *a, ll len)
    {
        for(ll i=1;i<=len;i++)
        {
            ll t=a[i];
            for(ll k(62);~k;k--)
                if(t&(1ll<<k))
                {
                    if(!b[k])b[k]=t;
                    t^=b[k];
                }
        }
    }
    bool check(ll x)
    {
        for(ll k(62);~k;k--)
            if(x&(1ll<<k))x^=b[k];
        return !x;
    }
}LB;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll a[maxn], x, y, n;
int main()
{
    ll i, q;
    n=read();
    for(i=1;i<=n;i++)a[i]=read();
    LB.clear();
    LB.build(a,n);
    q=read();
    while(q--)
        if(LB.check(read()^read()))printf("YES\n");
        else printf("NO\n");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章