Given a sequence of nn numbers a_1, a_2, \cdots, a_na1,a2,⋯,an and three functions.
Define a function f(l,r)f(l,r) which returns \oplus a[x]⊕a[x] (l \le x \le rl≤x≤r). The \oplus⊕ represents exclusive OR.
Define a function g(l,r)g(l,r) which returns \oplus f(x,y)(l \le x \le y \le r)⊕f(x,y)(l≤x≤y≤r).
Define a function w(l,r)w(l,r) which returns \oplus g(x,y)(l \le x \le y \le r)⊕g(x,y)(l≤x≤y≤r).
You are also given a number of xor-queries. A xor-query is a pair (i, ji,j) (1 \le i \le j \le n1≤i≤j≤n). For each xor-query (i, j)(i,j), you have to answer the result of function w(l,r)w(l,r).
Input
Line 11: t (1 \le t \le 20)t(1≤t≤20).
For each test case:
Line 11: n (1 \le n \le 100000)n(1≤n≤100000).
Line 22: nn numbers a_1, a_2, \cdots, a_n (1 \le a_i \le 10^9)a1,a2,⋯,an(1≤ai≤109).
Line 33: q (1 \le q \le 100000)q(1≤q≤100000), the number of xor-queries.
In the next qq lines, each line contains 22numbers i, ji,j representing a xor-query (1 \le i \le j \le n)(1≤i≤j≤n).
It is guaranteed that sum of nn and q \le 10^6q≤106.
Output
For each xor-query (i, j)(i,j), print the result of function w(i,j)w(i,j) in a single line.
样例输入复制
1 5 1 2 3 4 5 5 1 3 1 5 1 4 4 5 3 5
样例输出复制
2 4 0 1 4
题意:T组数据,每组数据先输入一个n , 然后n个数,q次查询,输出 w ( l , r );
规则:f( l , r ) = l ^ ( l + 1) ^ ( l + 2 ) ^ ... ^ r
g( l , r ) = f( x1 ,y1 ) ^ f(x2,y2) ^.... ( l <= xi , yi <= r )
w( l , r ) = g( x1 ,y1 ) ^ g(x2,y2) ^.... ( l <= xi , yi <= r )
思路:先暴力打表观察规律,
得出的结论是:从x开始,每四个点特性循环一次。
特性:假设有一些点 : a , b , c , d , e , f , g , h , i , j , k
1 - > 1: a
1 - > 2: a ^ b 2 - > 2: b
1 - > 3: b 2 - > 3: b ^ c
1 - > 4: 0 2 - > 4: c
1 - > 5: a ^ e 2 - > 5: 0
1 - > 6: a ^ b ^ e ^ f 2 - > 6: b ^ f
1 - > 7: b ^ f 2 - > 7: b ^ c ^ f ^ g
1 - > 8: 0 ^ 0 2 - > 8: c ^ g
也就是说,每4个一循环的特性不随起点而改变,只是在对应区间异或特性对应的值。
那么我们再来看:
5 - > 5 :e
5 - > 6 :e ^ f
5 - > 7: f
5 - > 8:0
也就是说:以5为开头的其实是可以通过以1为开头的找到的,同理以6开头可以在以2开头的里面找到,以7开头可以在以3开头的里面找到,以8开头可以在以4开头的里面找到.......
所以说我们只需要打一个 以 i 为开头,到达任意点的s的表就好了,我在这里假设为a[ i ][ j ] : 代表 以 i 开头,到达 j 点的值。
代码如下:
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
#define N 100010
using namespace std;
const double pi=acos(-1.0);
int a[N];
int v[5][N];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
memset(v,0,sizeof(v));
memset(a,0,sizeof(a));
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=4; i++) //以 i 开头
{
//4个一循环的 循环特性
for(int j=i; j<=n; j+=4) //第一个异或自己
{
if(j-4>=i)
v[i][j]=v[i][j-4]^a[j];
else
v[i][j]=a[j];
}
for(int j=i+1; j<=n; j+=4) //第二个 异或前两个值
{
if(j-4>=i)
v[i][j]=v[i][j-4]^a[j]^a[j-1];
else
v[i][j]=a[j]^a[j-1];
}
for(int j=i+2; j<=n; j+=4) //第三个 异或第二个值
{
if(j-4>=i)
v[i][j]=v[i][j-4]^a[j-1];
else
v[i][j]=a[j-1];
} //第四个是 0,省略
}
int m;
scanf("%d",&m);
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
if((r-l+1)%4==0) //区间长度为4的倍数,直接为0
printf("0\n");
else
{
if(l>4) //开头大于4,需要在[1,4]开头里面找
{
int p=l%4; //在以p开头里面找
if(p==0)p=4;
int x=l-4+(r-l)%4; //要把上一个 循环中的值给异或掉,x 为上一个循环中的哪一个
printf("%d\n",v[p][x]^v[p][r]);
}
else printf("%d\n",v[l][r]);
}
}
}
return 0;
}
/*
100
10
1 2 3 4 5 6 7 8 9 10
100
*/