很简单的一道题(虽然我没有做出来)
我们可以大致分一下块,dp[i][j]表示在对于i这个位置假设询问的状态为j,只考虑后面2^8位,那么答案是多少
利用lucas定理可以发现如果位置用i+k表示的话,k为j的子集时这个数才有贡献
那么就高位前缀和处理dp,剩下的枚举子集就做完了
#include<bits/stdc++.h>
using namespace std;
int dp[200305][260],a[200305],n,m,shu1,shu2;
int read()
{
register int x;register char c;
for(c=getchar();c!='-'&&(c>'9'||c<'0');c=getchar());
if(c=='-')
{
x=0;
for(c=getchar();c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
return -x;
}
else
{
x=c-'0';
for(c=getchar();c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
return x;
}
}
int main()
{
cin>>n>>m;
for(register int i=1;i<=n;i++)
a[i]=read();
for(register int i=1;i<=n;i++)
{
for(register int j=0;j<256;j++)
dp[i][j]=a[i+j];
}
for(register int j=0;j<8;j++)
{
for(register int i=1;i<=n;i++)
{
for(register int k=0;k<256;k++)
if((k>>j)&1)
dp[i][k]^=dp[i][k^(1<<j)];
}
}
register int all=(1<<8)-1;
for(int i=1;i<=m;i++)
{
shu1=read();shu2=read();
register int up=n-shu2,maxa;
for(maxa=1;maxa<=up;maxa<<=1);maxa--;
shu1&=maxa;
up=shu1>>8;register int down=shu1&all;
int ans=dp[shu2][down];
for(register int s=up;s;s=(s-1)&up)
if(shu2+(s<<8)<=n)
{
ans^=dp[shu2+(s<<8)][down];
}
printf("%d\n",ans);
}
return 0;
}