[异或前缀]梦境

题面

题目描述

相信你也和 O i e r Oier Oier- K r y Kry Kry 一样,码了几行代码,就轻松搞定其等价电阻的值。
K r y Kry Kry 忽然间意识到不能总是不干正经事,联赛马上就来了, 该整理下 U U U 盘,好好复习总结下,于是插上 U U U 盘,开始翻阅以前学习的资料。
由于前面的更换教室地板,再加上刚才解决电路连接问题, K r y Kry Kry 有点累了,不知道哪里来的困意,在学习压力这么大的情况下,居然不知不觉的睡着了
K r y Kry Kry 在梦里回到了初中时代, 仿佛感觉好像是 Mir.Z 在教室前面讲解联赛的题目,但又感觉不是,这个梦怎么这么不真实。 难道 M i r . Z Mir.Z Mir.Z 讲的题目和今年联赛有关, K r y Kry Kry 努力的回想着。由于 K r y Kry Kry 想让梦境清晰一点,着急的一下子从梦里惊醒了。 隐约只记得 M i r . Z Mir.Z Mir.Z 所讲的题目大概,具体描述如下:
有一个整数序列,暂且将其称为 X O R b o n a c c i XORbonacci XORbonacci 序列。序列中的第 N N N 个元素用 X N X_N XN表示。该序列按照以下方式递归定义:
X 1 X_1 X1 = = = X 1 X_1 X1
X 2 X_2 X2 = = = X 2 X_2 X2
… … ……
X K X_K XK = = = X K X_K XK
X N X_N XN = = = X N − 1 X_{N-1} XN1 ⨁ \bigoplus X N − 2 X_{N-2} XN2 ⨁ \bigoplus … … …… ⨁ \bigoplus X N − K X_{N-K} XNK ( N > k ) (N>k) (Nk)
Mir.Z 将会提出 Q 次询问,每次询问给出两个整数 L 和 R。而每次询问的答案即以下式子的值:
X L X_L XL ⨁ \bigoplus X L + 1 X_{L+1} XL+1 ⨁ \bigoplus … … …… ⨁ \bigoplus X R − 1 ⨁ X R X_{R-1}\bigoplus X_R XR1XR。注意:题目中的符号" ⨁ \bigoplus "在 K r y Kry Kry 的梦里应该是 X O R XOR XOR 异或。( P S : P a s c a l PS:Pascal PSPascal 语言异或运算符是 x o r xor xor C C C 语言或者 C + + C++ C++ 语言异或运算符是 ^)
O i e r Oier Oier 们抓紧解决这个小题吧,万一联赛要是真的出呢?那岂不是赚到了。

输入

第 1 行输入包含一个整数 k k k
接下来的一行包含 k k k 个整数,第 i i i个整数 A i A_i Ai 表示 X O R b o n a c c i XORbonacci XORbonacci 序列中的第 i i i 个元素;
接下来一行包含一个整数 Q Q Q
接下来的 Q Q Q 行,每行包含两个整数 L i L_i Li R i R_i Ri,表示 M i r . Z Mir.Z Mir.Z i i i 次询问的下标区间;

输出

输出共 Q Q Q 行,第 i 行输出 M i r . Z Mir.Z Mir.Z 的第 i i i 次询问的结果。

数据范围

对于 30%的数据: 1 ≤ k ≤ 5000 , 1 ≤ Q ≤ 5000 , 1 ≤ L i ≤ R i ≤ 5000 , 1 ≤ A i ≤ 5000 1≤k≤5000 ,1≤Q≤5000, 1≤L_i≤R_i≤5000, 1≤A_i≤5000 1k5000,1Q5000,1LiRi5000,1Ai5000
对于 50%的数据: 1 ≤ k ≤ 100000 , 1 ≤ Q ≤ 100000 , 1 ≤ L i ≤ R i ≤ 500000 , 1 ≤ A i ≤ 5000 1≤k≤100000 ,1≤Q≤100000, 1≤L_i≤R_i≤500000, 1≤A_i≤5000 1k100000,1Q100000,1LiRi500000,1Ai5000
对于 100%的数据: 1 ≤ k ≤ 100000 , 1 ≤ Q ≤ 100000 , 1 ≤ L i ≤ R i ≤ 1 0 18 , 1 ≤ A i ≤ 1 0 18 1≤k≤100000, 1≤Q≤100000, 1≤L_i≤R_i≤10^{18}, 1≤A_i≤10^{18} 1k100000,1Q100000,1LiRi1018,1Ai1018

思路分析

知识导入-前缀和(by 不想悲伤到天明)
根据同理,可以推出一个异或前缀数组:

前缀和异或前缀和
根据 ∑ i = 1 n a i \sum\limits_{i=1}^{n}{a_i} i=1nai ∑ i = 1 n ⨁ a i \sum\limits_{i=1}^{n}{\bigoplus a_i} i=1nai
可推出 ∑ i = 1 n a i = ∑ i = 1 n − 1 a i + a n \sum\limits_{i=1}^{n}{a_i} = \sum\limits_{i=1}^{n-1}{a_i}+a_n i=1nai=i=1n1ai+an ∑ i = 1 n ⨁ a i = ∑ i = 1 n − 1 ⨁ a i + a n \sum\limits_{i=1}^{n}{\bigoplus a_i} = \sum\limits_{i=1}^{n-1}{\bigoplus a_i}+a_n i=1nai=i=1n1ai+an
求区间 ∑ i = 1 r a i − ∑ i = 1 l − 1 a i \sum\limits_{i=1}^{r}{a_i}-\sum\limits_{i=1}^{l-1}{a_i} i=1raii=1l1ai ∑ i = 1 r ⨁ a i ⨁ ∑ i = 1 l − 1 ⨁ a i {\sum\limits_{i=1}^{r}{\bigoplus a_i} }\bigoplus {\sum\limits_{i=1}^{l-1}{\bigoplus a_i}} i=1raii=1l1ai

本来可以直接维护一个异或前缀数组的,但是 1 ≤ L i ≤ R i ≤ 1 0 18 1≤L_i≤R_i≤10^{18} 1LiRi1018
所以我们要看看有没有规律:
因为我们知道 n ⨁ n = 0 n\bigoplus n=0 nn=0 X N X_N XN = = = X N − 1 X_{N-1} XN1 ⨁ \bigoplus X N − 2 X_{N-2} XN2 ⨁ \bigoplus … … …… ⨁ \bigoplus X N − K X_{N-K} XNK ( N > k ) (N>k) (Nk)
所以可以推出 ∑ i = 1 k + 1 ⨁ a i = ∑ i = 0 0 ⨁ a i \sum\limits_{i=1}^{k+1}{\bigoplus a_i}=\sum\limits_{i=0}^{0}{\bigoplus a_i} i=1k+1ai=i=00ai也就是 0 0 0
接下来也可以看出

∑ i = 1 k + 1 ⨁ a i = ∑ i = 1 0 ⨁ a i \sum\limits_{i=1}^{k+1}{\bigoplus a_i}=\sum\limits_{i=1}^{0}{\bigoplus a_i} i=1k+1ai=i=10ai
∑ i = 1 k + 2 ⨁ a i = ∑ i = 1 1 ⨁ a i \sum\limits_{i=1}^{k+2}{\bigoplus a_i}=\sum\limits_{i=1}^{1}{\bigoplus a_i} i=1k+2ai=i=11ai
∑ i = 1 k + 3 ⨁ a i = ∑ i = 1 2 ⨁ a i \sum\limits_{i=1}^{k+3}{\bigoplus a_i}=\sum\limits_{i=1}^{2}{\bigoplus a_i} i=1k+3ai=i=12ai
……
∑ i = 1 k + X ⨁ a i = ∑ i = 1 ( k + x ) % ( K + 1 ) ⨁ a i \sum\limits_{i=1}^{k+X}{\bigoplus a_i}=\sum\limits_{i=1}^{(k+x)\%(K+1)}{\bigoplus a_i} i=1k+Xai=i=1(k+x)%(K+1)ai

完整代码

#include<bits/stdc++.h>
long long N,P,L,R;
long long a[100039],add[100039];
inline void read(register long long &x){
	x=0;register char c=getchar();register bool f=0;
	while(c<'0'||c>'9'){if(c=='-')f=1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
	if(f)x=-x;
}
int main() {
	read(N);
	for(register long long i=1;i<=N;i++){
		read(a[i]);
		add[i]=add[i-1]^a[i];
	}
	scanf("%lld",&P);
	for(register long long i=1;i<=P;i++){
		read(L),read(R);
		L%=N+1;R%=N+1;
		if(L==0)L=N+1;if(R==0)R=N+1;
		printf("%lld\n",add[L-1]^add[R]); 
	}
}//不足半K的代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值