题目链接: 题库链接
【题意】:
给出了很多定义式子出来,f(x,y)=下标从x到y异或和。
g(x,y)是[x,y]区间所有的区间的f(tx,ty) 的异或和,(x<=tx<=ty<=y)
w(x,y)是[x,y]区间所有的区间的g(tx,ty) 的异或和,(x<=tx<=ty<=y)
推导:g(x,y)是有规律可言的。
因为所有区间和,也可以算出每一个区间中每一个数字出现的个数。
例如[ 1, 4 ]:
4: 4*1
3: 3*2
2: 2*3
1: 1*4
如果是:[1,5]
5: 5*1
4: 4*2
3: 3*3
2: 2*4
1: 1*5
得到结果是:
如果 (x+y) 为奇数时:
g(x,y) = 0
如果 (x+y) 为偶数时:
g(x,y) = ( x ^ (x+2) ^ ……^ y )
然后需要推导w(x,y)
根据 相邻两项为0.其他都是相隔的。
然后直接推导即可。
w( 1, 1) = 1
w( 1, 2) =1^2
w( 1, 3) =2
w( 1, 4) =0
w( 1, 5) =1^5
w( 1, 6) =1^2^5^6
w( 1, 7) =2^6
w( 1, 8) =0
w( 1, 9) =1^5^9
w( 1, 10) =1^2^5^6^9^10
w( 1, 11) =2^6^10
w( 1, 12) =0
w( 1, 13) =1^5^9^13
w( 1, 14) =1^2^5^6^9^10^13^14
w( 1, 15) =2^6^10^14
w( 1, 16) =0
推导这里我就知道怎么一回事,
其实就是以4为一循环,然后进行第一项每隔4个异或 或者第二项开始每隔4个进行异或 。
如果要写,那么还需要看这个数在第几个4中。
大家看代码就明白了。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
int xor_sum[N][4];
int a[N];
int main()
{
int T;
scanf("%d",&T);
while(T--){
memset(xor_sum,0,sizeof(xor_sum));
int n,Q,L,R;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
xor_sum[i][i%4] = a[i]^xor_sum[i-1][i%4];
xor_sum[i][(i+1)%4] = xor_sum[i-1][(i+1)%4];
xor_sum[i][(i+2)%4] = xor_sum[i-1][(i+2)%4];
xor_sum[i][(i+3)%4] = xor_sum[i-1][(i+3)%4];
}
scanf("%d",&Q);
while(Q--){
int ans = 0 ;
scanf("%d%d",&L,&R);
if( (R-L)%4 == 0 ){
ans ^= xor_sum[R][L%4] ^ xor_sum[L-1][L%4];
}else if( (R-L)%4 == 1){
ans ^= xor_sum[R][L%4] ^ xor_sum[L-1][L%4];
ans ^= xor_sum[R][(L+1)%4] ^xor_sum[L-1][(L+1)%4];
}else if( (R-L)%4 == 2){
ans ^= xor_sum[R][(L+1)%4] ^xor_sum[L-1][(L+1)%4];
}else{
ans = 0;
}
printf("%d\n",ans);
}
}
return 0;
}
/*
int g(int x,int y){
int ans = 0 ;
if( (x+y) & 1)return 0;
for(int i=x;i<=y;i+=2){
ans ^=i;
}
return ans;
}
int w(int x,int y){
int ans = 0 ;
for(int i=x;i<=y;i++){
for(int len=1; i+len-1<=y;len+=2){
for(int x=i;x<=i+len-1;x+=2){
ans ^= x;
}
}
}
return ans ;
}
*/