Sum of xor jdoj-2160
题目大意:给你一个n,求1^2^...^n。
注释:$n<=10^{18}$。
想法:第一道异或的题。先来介绍一下什么是异或。a^b表示分别将两个数变成二进制后,从左到右按位取异或。两个异或字符,相同为0,不同为1。接下来,我们来证明异或的一些性质。
1.异或单位独立性。两个数的二进制,如果位数不够按位补全。我们显然可以证明,每一位上的异或显然独立的。
2.a^0=a,a^a=0。显然。
3.异或交换律。我们对于三个数来进行考虑。不妨设为a,b,c。我们只需证明a^b^c=a^(b^c)。显然,对于三个数的每一位来讲,必定有两个数相等(鸽巢原理)。所以,只剩下另一个数。如果相等的两个数是0,或1,我们都可以借助异或的第一条性质进行言简意赅的证明。
4.异或的诡异性质。任意的a属于$N^+$,都有4a^(4a+1)^(4a+2)^(4a+3)=0。有第一条即可证明。这是显然的,因为这四个数的除去最后两位都是一样的,有第一条性质,在前面去异或的时候都是0。然后,再有第2条性质,就可以证明。
异或的应用:假设有一段序列。所有的数都出现了两次,只有一个数出现了一次。全取异或,由第二条性质,证毕。
然后,关于这道题,我们发现,由第4条性质和第二条性质的前半部分,我们可以将这个异或和转化为不大于n的4的倍数到n的异或和。显然,迎刃而解。
最后,附上丑陋的代码... ...
1 #include <iostream> 2 #include <cstdio> 3 typedef long long ll; 4 using namespace std; 5 int main() 6 { 7 ll n; 8 scanf("%lld",&n); 9 ll ans=0; 10 for(ll i=n/4*4;i<=n;i++) 11 { 12 ans^=i; 13 } 14 printf("%lld\n",ans); 15 return 0; 16 }
小结:既然n是long long那么i也必须是long long。