The Preliminary Contest for ICPC China Nanchang National Invitational K. MORE XOR

MORE XOR

题目链接

  • 时间:1000ms
  • 内存:262144K

Given a sequence of nnn numbers a1,a2,⋯ ,ana_1, a_2, \cdots, a_na1,a2,,an and three functions.

Define a function f(l,r)f(l,r)f(l,r) which returns ⊕a[x]\oplus a[x]a[x] (l≤x≤rl \le x \le rlxr). The ⊕\oplus represents exclusive OR.

Define a function g(l,r)g(l,r)g(l,r) which returns ⊕f(x,y)(l≤x≤y≤r)\oplus f(x,y)(l \le x \le y \le r)f(x,y)(lxyr).

Define a function w(l,r)w(l,r)w(l,r) which returns ⊕g(x,y)(l≤x≤y≤r)\oplus g(x,y)(l \le x \le y \le r)g(x,y)(lxyr).

You are also given a number of xor-queries. A xor-query is a pair (i,ji, ji,j) (1≤i≤j≤n1 \le i \le j \le n1ijn). For each xor-query (i,j)(i, j)(i,j), you have to answer the result of function w(l,r)w(l,r)w(l,r).

Input

Line 111: t(1≤t≤20)t (1 \le t \le 20)t(1t20).

For each test case:

Line 111: n(1≤n≤100000)n (1 \le n \le 100000)n(1n100000).

Line 222: nnn numbers a1,a2,⋯ ,an(1≤ai≤109)a_1, a_2, \cdots, a_n (1 \le a_i \le 10^9)a1,a2,,an(1ai109).

Line 333: q(1≤q≤100000)q (1 \le q \le 100000)q(1q100000), the number of xor-queries.

In the next qqq lines, each line contains 222 numbers i,ji, ji,j representing a xor-query (1≤i≤j≤n)(1 \le i \le j \le n)(1ijn).

It is guaranteed that sum of nnn and q≤106q \le 10^6q106.

Output

For each xor-query (i,j)(i, j)(i,j), print the result of function w(i,j)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

题目来源:The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest

  • 大意:给出n个数a[1…n],定义了三种运算
    1、f(L,R)=a[L]到a[R]的异或和
    2、g(L,R)=f(L,L)到f(R,R)的异或和
    3、w(L,R)=g(L,L)到f(R,R)的异或和

给出多组区间,问w(L,R)的值

  • 分析:可以试一些简单的数,发现g(L,R)有个很明显的规律:若L到R之间的数是奇数个,那么g(L,R)的值为L,L+2,…,R这几个位置的数的异或和;若L到R之间的数是偶数个,则g(L,R)的值为0。
    因此,我们可以以w(1,5)为例,将其展开为g(L,R)的表达式,并将所需要的数的编号代入,如下表
12345
1101 301 3 5
2202 40
3303 5
440
55

表里共有3* 1个1,2* 2个3,1* 3个5,2* 1个2,1* 2个4

假设区间L到R中有n个数,记L为第一个,L+1为第2个,以此类推。
在这n个数中,处于奇数位置的数有nj=(n/2+n%2)个,处于偶数位置的数有no=(n/2)个。
若nj为奇数,那么L,L+4,…R1(不大于R)为异或和的一部分;
若no为奇数,那么L+1,L+1+4,…R2(不大于R)为异或和的一部分;
将L到R中符合上述条件的位置的数求异或和,即为w(L,R)的值。
可通过前缀和快速计算(L,R1)(L+1,R2)的异或和。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100005;
int a[maxn];
int sum[4][maxn];//4组前缀和
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(sum,0,sizeof(sum));
        int n;
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d",&a[i]);
            sum[(i-1)%4][(i-1)/4+1]=sum[(i-1)%4][(i-1)/4]^a[i];
        }
        //输出中间变量
        /*
        for(int i = 0; i < 4; ++i)
        {
            for(int j = 0; j  < 4; ++j)
                printf("%d ",sum[i][j]);
            printf("\n");
        }*/
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int nn = y-x+1;    //区间大小
            int no = nn/2;     //偶数个数
            int nj = no + nn%2;//奇数个数
            int ans = 0;
            if(nj&1)
            {
                int my = y;
                while((my-1)%4!=(x-1)%4) my--;
                //找到区间内x所在行的最后一个数的位置
                ans^=(sum[(x-1)%4][(x-1)/4]^sum[(x-1)%4][(my-1)/4+1]);
                //printf("===%d %d\n",(x-1)/4,(my-1)/4+1);
            }
            if(no&1)
            {
                x=x+1;
                int my = y;
                while((my-1)%4!=(x-1)%4) my--;
                //找到区间内x+1所在行的最后一个数的位置
                ans^=(sum[(x-1)%4][(x-1)/4]^sum[(x-1)%4][(my-1)/4+1]);
                //printf("---%d %d\n",(x-1)/4,(my-1)/4+1);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值