Codeforces957 Mahmoud and Ehab and yet another xor task

题意:长度为n的序列,q个查询,每次查询一个l,x问[1, l]中子序列异或出来等于x的个数

题解:这道题可以用线性基来处理

线性基是一个集合,它异或出来的集合与原集合异或相同

原集合异或出来的数可以由线性基唯一表示

一个数能遍历线性基得到0,这个数就可以被异或出来

那么这道题可以离线处理,对于每一个查询[l ,x],已经处理出来[1, l]的线性基,那么遍历一遍后可以知道x能否表示

计算个数的时候,因为一个线性基代表一个数,所以遍历后的num就是表示x所需要的数,而剩下的l-num个数,如果可以表示为y,那么这l个数就一定可以表示出y^x(因为前面是已经判断过x一定给可以表示)

所以答案就是2^(l-num)

#include <bits/stdc++.h>
#define maxn 100010
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int num;
struct L_B{
    ll d[61],p[61];
    int cnt;
    L_B()
    {
        memset(d,0,sizeof(d));
        memset(p,0,sizeof(p));
        cnt=0;
    }
    bool insert(ll val)
    {
        for (int i=60;i>=0;i--)
            if (val&(1LL<<i))
            {
                if (!d[i])
                {
                    d[i]=val;
                    break;
                }
                val^=d[i];
            }
        return val>0;
    }
    ll query_max()
    {
        ll ret=0;
        for (int i=60;i>=0;i--)
            if ((ret^d[i])>ret)
                ret^=d[i];
        return ret;
    }
    ll query_min()
    {
        for (int i=0;i<=60;i++)
            if (d[i])
                return d[i];
        return 0;
    }
    void rebuild()
    {
        for (int i=60;i>=0;i--)
            for (int j=i-1;j>=0;j--)
                if (d[i]&(1LL<<j))
                    d[i]^=d[j];
        for (int i=0;i<=60;i++)
            if (d[i])
                p[cnt++]=d[i];
    }
    ll kthquery(ll k)
    {
        int ret=0;
        if (k>=(1LL<<cnt))
            return -1;
        for (int i=60;i>=0;i--)
            if (k&(1LL<<i))
                ret^=p[i];
        return ret;
    }
    bool query(ll x){
        num = 0;
        for(int i=60;i>=0;i--){
            if(d[i]){
                num++;
                if(x&(1LL<<i))
                    x ^= d[i];
            }
        }
        return x==0;
    }
}b;
L_B merge(const L_B &n1,const L_B &n2)
{
    L_B ret=n1;
    for (int i=60;i>=0;i--)
        if (n2.d[i])
            ret.insert(n1.d[i]);
    return ret;
}
ll f(ll a,ll b){
    ll mod = 1e9+7;
    a %= mod;
    ll ans = 1;
    while(b){
        if(b&1) ans = ans*a%mod;
        a = a*a%mod;
        b >>= 1;
    }
    return ans;
}
ll a[maxn], ans[maxn], l, x;
vector<pair<ll ,ll > >G[maxn];
int main(){
    ll n, q;
    cin>>n>>q;
    for(int i=1;i<=n;i++)
        scanf("%lld", &a[i]);
    for(int i=1;i<=q;i++){
        scanf("%lld%lld", &l, &x);
        G[l].push_back(make_pair(i, x));
    }
    for(int i=1;i<=n;i++){
        b.insert(a[i]);
        for(auto j:G[i]){
            if(b.query(j.second))
                ans[j.first] = f(2, (i-num));
        }
    }
    for(int i=1;i<=q;i++)
        cout<<ans[i]<<endl;
    return 0;
}

 

posted on 2018-04-07 17:16  2855669158  阅读(185)  评论(0编辑  收藏  举报

导航