题意
给定 \(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;
}
标签:task,xor,ll,lst,Mahmoud,线性,return,复杂度,dis
From: https://www.cnblogs.com/run-away/p/18144003