「CF959F」 Mahmoud and Ehab and yet another xor task

题意

给定 \(n\) 个整数 \(a_i\)\(q\) 次形如 \(l\ x\) 的提问,每次提问输出 \(a_1\sim a_l\) 中有多少个子序列满足异或和为 \(x\)

分析

很明显的线性基,因为数组开 \(20n\) 不会炸,所以可以直接建立 \(n\) 个线性基,记录 \(a_1\sim a_i\) 的线性基。

但是注意时间,因为下一位的线性基可以直接继承上一位的,所以在求解线性基时可加入 *this=lst,其中 \(lst\) 表示上一位的线性基,把时间复杂度降到 \(O(n)\)

询问复杂度为 \(O(q\log n)\),总时间复杂度为 \(O(q\log n)\)

Code

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
const ll mod=1e9+7,maxn=1e5+5,maxj=25;
struct basis{
    ll p[maxj];
    inline ll highbit(ll x){ll res=0;while(x)++res,x>>=1;return res;}
    inline void ins(basis lst,ll x){*this=lst;while(x){ll dis=highbit(x);if(p[dis])x^=p[dis];else return p[dis]=x,void();}}
    inline ll size(){ll res=0;for(ll i=1;i<=maxj;++i)res+=p[i]!=0;return res;}
    inline ll sum(ll x){ll res=0;while(x){ll dis=highbit(x);if(p[dis])x^=p[dis],++res;else return -1;}return x?res:size();}
}base[maxn];//线性基模板
ll n,q,a[maxn];
inline ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod,b>>=1;
    }
    return res;
}
signed main(){
    n=read(),q=read();
    for(ll i=1;i<=n;++i)a[i]=read(),base[i].ins(base[i-1],a[i]);
    while(q--){
        ll l=read(),x=read();
        ll res=base[l].sum(x);
        printf("%lld\n",res==-1?0:qpow(2,l-res));
    }
    return 0;
}
posted @ 2024-12-20 15:34  run-away  阅读(11)  评论(0)    收藏  举报