题意:
给定一个序列a,每次询问给出
l
l
,,询问前
l
l
个数中异或和为的方案数
题解:
设集合
V
V
的线性基为
对于线性基可以表示的所有的数,出现次数都是
2|V|−|β|
2
|
V
|
−
|
β
|
从前往后不断加入时,不同的线性基不会超过
log(amax)
l
o
g
(
a
m
a
x
)
个,所以只需要预处理所有前缀的线性基就可以做到
O(log)
O
(
l
o
g
)
的在线查询
//by sdfzchy
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int inf=(1<<30);
inline LL in()
{
char ch=getchar();
LL f=1,tmp=0;
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {tmp=(tmp<<1)+(tmp<<3)+(ch-'0');ch=getchar();}
return tmp*f;
}
const int mod=1e9+7;
const int N=100010;
int n,m;
LL a[N],mi[N];
struct LB
{
LL a[61],cnt;
bool ins(LL x)
{
for(int i=60;i>=0;i--) if(x&(1ll<<i))
{
if(!a[i]) {a[i]=x;cnt++;break;}
x^=a[i];
}
return x>0;
}
}Xor[100];
LL query(const LB &c,LL x,int p)
{
for(int i=60;i>=0;i--)if(x&(1ll<<i))
{
if(!c.a[i]) return 0;
x^=c.a[i];
}
if(x>0) return 0;
return mi[p-c.cnt];
}
int tot,bel[N];
int main()
{
n=in();m=in();
mi[0]=1;
for(int i=1;i<N;i++) mi[i]=mi[i-1]*2%mod;
for(int i=1;i<=n;i++)
{
LL x=in();
LB cur=Xor[tot];
if(cur.ins(x)) Xor[++tot]=cur;
bel[i]=tot;
}
for(int i=1;i<=m;i++)
{
LL l=in(),x=in();
printf("%I64d\n",query(Xor[bel[l]],x,l));
}
return 0;
}