【19南昌网络赛-K】【找规律】MORE XOR

 

题目链接: 题库链接

【题意】:

给出了很多定义式子出来,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 ;
}
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值