说明
- (oplus x)为累异或
- $ x^{oplus(a)}$为异或幂
题意&解法
$ f(l,r)=oplus_{i=l}^{r} a[i]( ) g(l,r)=oplus_{i=l}{r}a[i]{oplus((i-l+1)*(r-i+1))}$
(egin{alignat}{} w(l,r)&=oplus_{i=l}^{r}a[i]^{oplus(frac{(i-l+1)*(i-l+2)}2*frac{(r-i+1)*(i-l+2)}2)}&\&=egin{cases}a[l]oplus a[l+4]oplus cdotsoplus a[r]&len ext{%}4=1\a[l]oplus a[l+1]oplus s[l+4]oplus a[l+5]opluscdotsoplus a[r-1]oplus a[r]&len ext{%}4=2\a[l+1]oplus a[l+5]opluscdotsoplus a[r-1]&len ext{%}4=3\0&len ext{%}4=4end{cases}&(len=r-l+1)end{alignat})
即f(l,r)
为异或和,g(l,r)
为(i
在l-r
的所有子区间中出现次数的异或幂) 的累异或,w(l,r)
为(i
在l-r
的所有子区间的所有子区间中出现次数 的异或幂) 的累异或
步骤
- 四组出前缀异或打表
- 按区间长度和
l
所在位置分组计算
代码
#include<cstdio>
using namespace std;
const int maxn=100005;
int t,n,q,a[maxn],sum[maxn];
inline int Sum(int l,int r)
{
if(l-4>=0)
return sum[r]^sum[l-4];
else
return sum[r];
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]),
i-4>=0?sum[i]=sum[i-4]^a[i]:sum[i]=a[i];
scanf("%d",&q);
for(int i=0,l,r;i<q;i++)
{
int ans;
scanf("%d%d",&l,&r);l--;r--;
if((r-l+1)%4==1){//l...l+4...l+8...r
ans=Sum(l,r);
}
else if((r-l+1)%4==2){//l.l+1...l+4.l+5...r-1.r
ans=Sum(l,r-1)^Sum(l+1,r);
}
else if((r-l+1)%4==3){//l+1...l+5...r-1
ans=Sum(l+1,r-1);
}
else
ans=0;
printf("%d
",ans);
}
}
return 0;
}