【数学】MORE XOR

这篇博客讨论了一种利用异或运算的性质解答序列异或查询的方法。通过对给定序列进行特定间隔的前缀异或和计算,可以快速得出不同范围内的w(l, r)值,从而在O(1)时间内回答每个查询。博主通过打表发现了当范围长度模4的余数与答案之间的关系,并提供了相应的解题思路和代码实现。" 82694233,6393462,C++虚继承内存布局解析,"['C++编程', '面向对象', '内存管理', '继承原理']
摘要由CSDN通过智能技术生成

Given a sequence of n n n numbers a 1 , a 2 , ⋯   , a n a_1, a_2,\cdots, a_n a1,a2,,an and three functions.

Define a function f ( l , r ) f(l,r) f(l,r) which returns ⊕ a [ x ] ( l ≤ x ≤ r ) \oplus a[x] (l \le x \le r) a[x](lxr). 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 ) ⊕ f ( x , y ) \oplus f(x,y)(l \le x \le y \le r)⊕f(x,y) f(x,y)(lxyr)f(x,y).

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

You are also given a number of xor-queries. A xor-query is a pair ( i , j ) ( 1 ≤ i ≤ j ≤ n ) (i,j) (1 \le i \le j \le n) (i,j)(1ijn). 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 1 1 1: t ( 1 ≤ t ≤ 20 ) t (1 \le t \le 20) t(1t20).

For each test case:

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

Line 2 2 2: n n n numbers a 1 , a 2 , ⋯   , a n ( 1 ≤ a i ≤ 1 0 9 ) a_1, a_2, \cdots, a_n (1 \le a_i \le 10^9) a1,a2,,an(1ai109)

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

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

It is guaranteed that sum of n n n and q ≤ 1 0 6 q \le 10^6 q106

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

解题思路:
emmmm,我这道题是通过打表寻找规律来解答的。。。
打表的代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
int arr[100];
int main() 
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    freopen("out.txt", "w", stdout);
    ios::sync_with_stdio(0),cin.tie(0);
	for(int l1=1,r1=1;r1<=50;r1++) {
		memset(arr,0,sizeof arr);
		for(int l2=l1;l2<=r1;l2++) {
		for(int r2=l2;r2<=r1;r2++) {
			for(int l3=l2;l3<=r2;l3++) {
			for(int r3=l3;r3<=r2;r3++) {
				for(int k=l3;k<=r3;k++) {
					arr[k]++;
				}
			}
			}
		}
		}
		//输出的1代表最后的答案这项存在,0代表不存在
    	for(int i=1;i<=r1;i++) {
    		if(arr[i]%2==0) printf("0 ");
    		else printf("1 ");
    	}
    	printf("\n");
    	//例如假设区间为[l,r],第一行代表当区间长度为1时,其答案就是a[l]
    	//当区间长度为2时,其答案为a[l]^a[r]
    	//当区间长度为3时,其答案为a[l+1]
    	//当区间长度为4时,其答案为0
	}
    return 0;
}

通过表格我们可以发现,
( r − l + 1 ) % 4 = 0 (r-l+1) \%4=0 (rl+1)%4=0时,答案为 0 0 0
( r − l + 1 ) % 4 = 1 (r-l+1) \%4=1 (rl+1)%4=1时,答案为 a [ l ] ⊕ a [ l + 4 ] ⊕ a [ l + 8 ] ⋯ a [ r ] a[l]\oplus a[l+4] \oplus a[l+8] \cdots a[r] a[l]a[l+4]a[l+8]a[r]
( r − l + 1 ) % 4 = 2 (r-l+1) \%4=2 (rl+1)%4=2时,答案为 a [ l ] ⊕ a [ l + 1 ] ⊕ a [ l + 4 ] ⊕ a [ l + 5 ] ⋯ a [ r − 1 ] ⊕ a [ r ] a[l]\oplus a[l+1] \oplus a[l+4] \oplus a[l+5] \cdots a[r-1] \oplus a[r] a[l]a[l+1]a[l+4]a[l+5]a[r1]a[r]
( r − l + 1 ) % 4 = 3 (r-l+1) \%4=3 (rl+1)%4=3时,答案为 a [ l + 1 ] ⊕ a [ l + 5 ] ⊕ a [ l + 9 ] ⋯ a [ r − 1 ] a[l+1]\oplus a[l+5] \oplus a[l+9] \cdots a[r-1] a[l+1]a[l+5]a[l+9]a[r1]
因为有 1 0 6 10^6 106组查询,所以还需要求一个间隔为 4 4 4的前缀异或和,这样就可以实现 O ( 1 ) O(1) O(1)查询
代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <set>
#include <utility>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define inf 0x3f3f3f3f
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define lep(i,l,r) for(int i=l;i>=r;i--)
#define ms(arr) memset(arr,0,sizeof(arr))
//priority_queue<int,vector<int> ,greater<int> >q;
const int maxn = (int)1e5 + 5;
const ll mod = 1e9+7;
int arr[100100];
int sum[4][100100];
int main() 
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    //freopen("out.txt", "w", stdout);
    ios::sync_with_stdio(0),cin.tie(0);
    int t;
    scanf("%d",&t);
    while(t--) {
    	int n;
    	scanf("%d",&n);
    	rep(i,1,n) {
    		scanf("%d",&arr[i]);
    		sum[0][i]=sum[1][i]=sum[2][i]=sum[3][i]=0;
    	}
    	sum[1][1]=arr[1];
    	sum[2][2]=arr[2];
    	sum[3][3]=arr[3];
    	sum[0][4]=arr[4];
    	rep(i,5,n) {
    		sum[1][i]=sum[1][i-4]^arr[i];
    		sum[2][i+1]=sum[2][i+1-4]^arr[i+1];
    		sum[3][i+2]=sum[3][i+2-4]^arr[i+2];
    		sum[0][i+3]=sum[0][i+3-4]^arr[i+3];
    	}
    	int q;
    	scanf("%d",&q);
    	rep(i,1,q) {
    		int l,r;
    		scanf("%d%d",&l,&r);
    		int len=r-l+1,ans;
    		if(len%4==0) printf("0\n");
    		else if(len%4==1) {
    			ans=sum[r%4][r]^sum[l%4][l]^arr[l];
    			printf("%d\n",ans);
    		}
    		else if(len%4==2) {
    			ans=sum[r%4][r]^sum[(l+1)%4][l+1]^arr[l+1];
    			ans=ans^(sum[(r-1)%4][r-1]^sum[l%4][l]^arr[l]);
    			printf("%d\n",ans);
    		}
    		else {
    			ans=sum[(r-1)%4][r-1]^sum[(l+1)%4][l+1]^arr[l+1];
    			printf("%d\n",ans);
    		}
    	}
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值