题意
给出两个公式:
f(i,j)=ai^ (ai+1)^ (ai+2)^ …^aj 。(此为异或和,虽然为和但是是许多数的异或结果)
s=[f(1,1) ^ f(1,2) … f(1,n) ] ^ [f(2,2) ^ f(2,3) … f(2,n)] ^ [f(n,n)]
求出s的最终结果.
题解
首先要知道一件事情,异或的逆运算是异或
所以假设k1=[f(1,1) ^ f(1,2) … f(1,n) ],其中a[1]是被异或了(n-1+1)次
那么k2=[f(2,2) ^ f(2,3) … f(2,n)] ,只需要把k1异或的(n-1+1)次a[1]异或掉就是k2。
同理k3=k2异或(n-2+1)次a[2],k4=k3异或(n-3+1)次a[3] …
最终答案就是k1到kn的异或和。
所以只需要从头到尾扫一遍即可出结果。
这里还要知道一件事可以使上述过程简化,任何数异或它本身=0,任何数异或0是它本身,所以一个数自身异或奇数次是它本身,自身异或偶数次是0。
————————————————
版权声明:本文为CSDN博主「晚樱。」的原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45530271/article/details/103809647
此为出题人的题解,我本来想用递归求,不过会超时。
偶数个相同的数异或时为0,而奇数个则为其本身。
下面代码中的第一个循环是为了求出k1。第二个循环中的ans表示的是每次异或ki得到的结果,其中的now表示的是ki。k1循环一次更新一次,ans也是。
代码
#include
#include
using namespace std;
const int N=100007;
int a[N],ans,now,n,t;
int main(){
cin>>t;
while(t–){
cin>>n;
now=ans=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if((n-i+1)%2)now^=a[i];
}
for(int i=1;i<=n;i++){
ans^=now;
if((n-i+1)%2)now^=a[i];
}
cout<<ans<<endl;
}
}