【原创】UOJ 350 新年的XOR

新年的XOR

题目描述

在动物行为学中,Alpha对应动物群体中等级最高的个体,简而言之,就是人赢,那么AlphaGo自然就是人赢狗了。

但是狗群中还有众多的SingleDog,平日里他们和AlphaGo和谐相处,忍受着酸臭味自得其乐的活下去。但在2月14日这天,当AlphaGo在SingleDog们最后的防线——朋友圈秀恩爱的时候,他们实在按耐不住,决定密谋用FFF团的黑暗力量,打败AlphaGo。

但是AlphaGo的智商很高,很快便拦截了SingleDog们传输消息的异或值。为了让AlphaGo相信,SingleDog们只是在数朋友圈里的狗粮数,你,勇敢无畏的跳蚤,决定编造一个弥天大谎。

AlphaGo截获的是一个整数 n n n,你需要构造一个长度大于 1 1 1 的区间 [ L , R ] [L,R] [L,R]使得区间中所有整数的异或和恰好为 n n n

输入格式

第一行输入一个整数 t t t 表示数据组数。

接下来 t t t 行每行一个整数 n n n

输出格式

每组数据输出两个空格隔开的整数 L , R L,R L,R,表示你构造的区间。要求 1 ≤ L < R ≤ 1 0 1 8 1≤L<R≤10^18 1L<R1018

输入保证存在这样的区间。

样例

input

3
0
4
12

output

8 67
97 100
87 90

限制与约定

测试点编号 n n n的规模其他
1,2 n ≤ 100 n≤100 n100
3,4 n ≤ 2 × 1 0 3 n≤2×10^3 n2×103
5,6 n ≤ 1 0 6 n≤10^6 n106
7,8 n ≤ 1 0 18 n≤10^{18} n1018存在 ∥ R − n ∥ ≤ 100 \|R−n\|≤100 Rn100的合法解
9,10 n ≤ 1 0 18 n\leq10^{18} n1018

对于 100 100% 100 的数据, n ≥ 0 , 1 ≤ t ≤ 100 n≥0,1≤t≤100 n0,1t100
时间限制: 1 s 1s 1s
空间限制: 256 M B 256MB 256MB

分析

一点一点来。
我们可以枚举区间,然后暴力求异或和。 Θ ( n 3 ) \Theta(n^3) Θ(n3)
我们可以求前缀异或和,于是枚举对于每个区间就可以 Θ ( 1 ) \Theta(1) Θ(1)计算异或和了, Θ ( n 2 ) \Theta(n^2) Θ(n2)
于是我们想到用个桶之类的东西,一边求前缀异或和,一边存对于每个异或前缀和值在哪个位置出现过了,如果 S [ i ] ⊕ n S[i]\oplus n S[i]n已经出现了,就找到了。
因为 a ⊕ b = c    ⟺    a ⊕ c = b a\oplus b=c \iff a\oplus c=b ab=cac=b,而我们求前缀异或和(记 S [ x ] S[x] S[x]为1~x的前缀异或和) n = S [ r ] ⊕ S [ l − 1 ] n=S[r]\oplus S[l-1] n=S[r]S[l1]    ⟺    S [ l − 1 ] = S [ r ] ⊕ n \iff S[l-1]=S[r]\oplus n S[l1]=S[r]n了。
于是现在优化到了 Θ ( n ) \Theta(n) Θ(n)


打了个表发现惊奇的规律, { n % 4 = 0 时 , S [ n ] = n 。 n % 4 = 1 时 , S [ n ] = 1 。 n % 4 = 2 时 , S [ n ] = n + 1 。 n % 4 = 3 时 , S [ n ] = 0 。 \begin{cases}n\%4=0时,S[n]=n。\\ n\%4=1时,S[n]=1。\\ n\%4=2时,S[n]=n+1。\\n\%4=3时,S[n]=0。\end{cases} n%4=0S[n]=nn%4=1S[n]=1n%4=2S[n]=n+1n%4=3S[n]=0
这也非常容易证明,因为 ( 2 k ) ⊕ ( 2 k + 1 ) = 1 (2k)\oplus(2k+1)=1 (2k)(2k+1)=1,如果n是奇数,后面的若干对奇偶双双异或起来,都抵消成了1,总共 n − 1 2 \frac{n-1}{2} 2n1个,然后把这些个1和最前头的孤单的1异或起来,就得到了 S [ n ] = n + 1 2 个 1 的 异 或 和 = n + 1 2 & 1 S[n]=\frac{n+1}{2}个1的异或和=\frac{n+1}{2}\&1 S[n]=2n+11=2n+1&1;如果n是偶数,你既可以把后面的若干对奇偶双双异或起来再异或起1和2,也可以 S [ n ] = S [ n − 1 ] ⊕ n S[n]=S[n-1]\oplus n S[n]=S[n1]n,所以 S [ n ] = n + ( n + 1 2 & 1 ) S[n]=n+(\frac{n+1}{2}\&1) S[n]=n+(2n+1&1)
(去年的NOIp2030模拟赛用了这个结论但没有证明,看来我比去年强了一些。)
(因为去年是N合1,这个东西不是重点)
P.S.:
( 2 k ) ⊕ ( 2 k − 1 ) ≠ 1 (2k)\oplus(2k-1)\neq 1 (2k)(2k1)=1
S [ 5 ] = 1 ⊕ 2 ⊕ 3 ⊕ 4 ⊕ 5 = 1 ⊕ ( 2 ⊕ 3 ) ⊕ ( 4 ⊕ 5 ) = 1 ⊕ 1 ⊕ 1 = 1 S[5]=1\oplus 2\oplus 3\oplus 4\oplus 5=1\oplus (2\oplus 3)\oplus (4\oplus 5)=1\oplus1\oplus1=1 S[5]=12345=1(23)(45)=111=1
S [ 6 ] = S [ 5 ] ⊕ 6 = 1 ⊕ 2 ⊕ 3 ⊕ 4 ⊕ 5 ⊕ 6 = 1 ⊕ ( 2 ⊕ 3 ) ⊕ ( 4 ⊕ 5 ) ⊕ 6 = 1 ⊕ 6 = 7 S[6]=S[5]\oplus 6=1\oplus 2\oplus 3\oplus 4\oplus 5 \oplus 6=1\oplus (2\oplus 3)\oplus (4\oplus 5)\oplus 6=1\oplus 6=7 S[6]=S[5]6=123456=1(23)(45)6=16=7


这个结论有什么用呢?
如果 n % 4 = 0 n\%4=0 n%4=0,那就输出[1,n];
如果 n % 4 = 2 n\%4=2 n%4=2,那就输出[2,n];
如果 n % 4 = 3 n\%4=3 n%4=3,那就输出[1,n-1];
如果 n % 4 = 1 n\%4=1 n%4=1,因为 S [ n − 1 ] = n − 1 = S [ n − 4 ] ⊕ ( n − 3 ) ⊕ ( n − 2 ) ⊕ ( n − 1 ) = 1 ⊕ ( n − 3 ) ⊕ ( n − 2 ) ⊕ ( n − 1 ) S[n-1]=n-1=S[n-4]\oplus(n-3)\oplus(n-2)\oplus(n-1)=1\oplus(n-3)\oplus(n-2)\oplus(n-1) S[n1]=n1=S[n4](n3)(n2)(n1)=1(n3)(n2)(n1),于是发现 ( n − 3 ) ⊕ ( n − 2 ) ⊕ ( n − 1 ) = n (n-3)\oplus(n-2)\oplus(n-1)=n (n3)(n2)(n1)=n,所以输出[n-3,n-1]。
( n − 3 ) ⊕ ( n − 2 ) ⊕ ( n − 1 ) = 偶 ⊕ 奇 ⊕ 偶 = 奇 , 奇 ⊕ 1 = 奇 − 1 (n-3)\oplus(n-2)\oplus(n-1)=偶\oplus 奇\oplus偶=奇,奇\oplus 1=奇-1 (n3)(n2)(n1)==1=1)。

然后对于0、1、2特判一下。
于是A了。

翻了翻排名前几(十)名的代码,发现他们都是对于n是奇数输出 [ n − 3 , n − 1 ] [n-3,n-1] [n3,n1],对于n是偶数输出 [ n − 4 , n ] [n-4,n] [n4,n],然后特判0~4。
也是对的,挺好证明,可以按照n%4的余数分类,每一类就用上面的结论就好了。

代码

#include<cstdio>
#include<iostream>
using namespace std;

long long T,n;
int main()
{
	cin>>T;
	while(T--)
	{
		cin>>n;
		if(n==1) puts("2 3");
		else if(n==0) puts("1 3");
		else if(n==2) puts("3 5");
		else if(n%4==0) cout<<1<<" "<<n<<endl;
		else if(n%4==2) cout<<2<<" "<<n<<endl;
		else if(n%4==3) cout<<1<<" "<<n-1<<endl;
		else cout<<n-3<<" "<<n-1<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值