Given a sequence of n n n numbers a 1 a_1 a1, a 2 a_2 a2, ⋯ \cdots ⋯, a n a_n an and three functions.
Define a function f(l,r)f(l,r) which returns ⊕ \oplus ⊕ a[x] (l ≤ \le ≤ x ≤ \le ≤ 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).
Define a function w(l,r)w(l,r) which returns ⊕ \oplus ⊕ g(x,y)(l ≤ \le ≤ x ≤ \le ≤ y ≤ \le ≤ r).
You are also given a number of xor-queries. A xor-query is a pair (i, j) (1 ≤ \le ≤ i ≤ \le ≤ j ≤ \le ≤). For each xor-query (i, j), you have to answer the result of function w(l,r).
Input
Line 1: t (1 ≤ \le ≤ t ≤ \le ≤ 20).
For each test case:
Line 1: n (1 ≤ \le ≤ n ≤ \le ≤ 100000).
Line 2: n numbers a 1 a_1 a1, a 2 a_2 a2, ⋯ \cdots ⋯, a n a_n an (1 ≤ \le ≤ a i a_i ai ≤ \le ≤ 10^9).
Line 3: q (1 ≤ \le ≤ q ≤ \le ≤ 100000), the number of xor-queries.
In the next q lines, each line contains 2 numbers i, j representing a xor-query (1 ≤ \le ≤ i ≤ \le ≤ j ≤ \le ≤ n).
It is guaranteed that sum of nn and q ≤ \le ≤ 10^6.
Output
For each xor-query (i, j), print the result of function 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
求W(l,r)
W(l,r) = 所有的g(x,y) { (x,y)| x,y ∈ (l, l+1, l+2, …, r) } 的异或
g(l,r) = 所有的 f(x,y) { (x,y)| x,y ∈ (l, l+1, l+2, …, r) } 的异或
f(l,r) = 所有的 X i X_i Xi { i | i ∈ (l, l+1, l+2, …, r) } 的异或
通过写了几组样例,发现g(l,r) 的值 与 X l X_l Xl … \dots … X r X_r Xr 以及 len=r-l+1 有关。
将 X l X_l Xl … \dots … X r X_r Xr 从原数组抽出来找规律,即将 X l X_l Xl … \dots … X r X_r Xr 转化为 t 1 t_1 t1 … \dots … t l e n t_{len} tlen
通过列举情况:
得到一张表F1:
len | 系数 |
---|---|
1 | 1 |
2 | 2 2 |
3 | 3 4 3 |
4 | 4 6 6 4 |
… | … |
其中第n行是由下面的三角形进行前缀和运算得到
1
1 2
1 2 3
1 2 3 4
…
表F1能干什么:
对与一个g(l ,r) , 若len = r - l + 1 = 2; 则有g(l, r) = 2 个 X l X_l Xl 和 2 个 X r X_r Xr 的异或
同理, len = r - l + 1 = 3; 则有g(l, r) = 3 个 X l X_l Xl 和 6 个 X l + 1 X_{l+1} Xl+1 以及 3 个 X r X_r Xr 的异或
在定义一个c[i][j], i 代表所求区间长度为i, j 代表第j项的系数
经枚举样例
有 c[i][j] = ( i + j ) j 2 \frac{ (i+j)j }{2} 2(i+j)j ∗ \ast ∗ ( 1 + i − j + 1 ) ( i − j + 1 ) 2 \frac{ (1+i-j+1)(i-j+1) }{2} 2(1+i−j+1)(i−j+1)
于是对W(l , r), 当 len=r-l+1 有 W(l , r) = c[2][1] 个 X l X_l Xl 和 c[2][2] 个 X r X_r Xr 的异或
len | 系数 |
---|---|
1 | 1 |
2 | 3 3 |
3 | 6 9 6 |
4 | 10 18 18 10 |
… | … |
利用 a ^ a = 0, a ^ 0 = a;
只需找出系数为奇数的数,再进行一次异或就行。
有
len | 奇偶性 |
---|---|
1 | 1 |
2 | 1 1 |
3 | 0 1 0 |
4 | 0 0 0 0 |
5 | 1 0 0 0 1 |
6 | 1 1 0 0 1 1 |
7 | 0 1 0 0 0 1 0 |
8 | 0 0 0 0 0 0 0 0 |
9 | 0 1 0 0 0 1 0 0 1 |
10 | 1 1 0 0 1 1 0 0 1 1 |
… | … |
仔细观察,
将系数序列每4个分成一段,有:
终于将规律找出来了,可这样写会超时,还要用一下前缀和。前缀和也要修改一下。
#include
#include
#include
#include
#include
using namespace std;
typedef long long int LL;
const int N = 100100;
LL a[N];
LL sum[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
LL n;
scanf("%lld",&n);
memset(sum,0,sizeof(sum));
for(LL i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
if(i <= 4)
sum[i] = a[i];
else
sum[i] = sum[i-4] ^ a[i];
}
LL l,r;
LL q;
scanf("%lld",&q);
while(q--)
{
scanf("%lld%lld",&l,&r);
LL len = r - l + 1;
LL ans = 0;
if(len % 4 == 1)
{
if(len == 1)
ans = a[l];
else
ans = sum[r] ^ sum[ ((l-4<0) ? 0 : (l-4)) ];
}
else if(len % 4 == 2)
{
if(len == 2)
ans = a[r] ^ a[l];
else
ans = sum[r] ^ sum[r - 1] ^ sum[ ((l-4<0) ? 0 : l-4) ] ^ sum[ ((l-4+1<0) ? 0 : l-4+1) ];
}
else if(len % 4 == 3)
{
if(len == 3)
ans = a[l+1];
else
ans = sum[r - 1] ^ sum[ ((l-4+1<0) ? 0 : l-4+1) ];
}
printf("%lld\n",ans);
}
}
return 0;
}
总结
超时可以用前缀和优化
前缀和别求错了