首先看一下题吧:题意就是让你把一个序列里所有的(Ai+Aj) 的异或求出来。(1<=i,j<=n)
Problem Description
MZL loves xor very much.Now he gets an array A.The length of A is n.He wants to know the xor of all (Ai+Aj)(1≤i,j≤n)
The xor of an array B is defined as B1 xor B2...xor Bn
Input
Multiple test cases, the first line contains an integer T(no more than 20), indicating the number of cases.
Each test case contains four integers:n,m,z,l
A1=0,Ai=(Ai?1?m+z) mod l
1≤m,z,l≤5?105,n=5?105
Output
For every test.print the answer.
Sample Input
2 3 5 5 7 6 8 8 9
Sample Output
14 16
比赛的时候我们是先暴力把序列求出来,然后再n^2的复杂度求出和的异或,值是对的,说明想法没错,但是YY立马发现复杂度太高,绝B 超时,赛场上没管那没多,直接求序列 Ai 的异或,发现此值是 sample out 的二倍,又找了几组例子无错,果断A之。
code:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<queue> #include<stack> #include<map> #include<iostream> #include<set> using namespace std; #define LL long long #define _LL __int64 #define max1(a,b) (a)>(b)?(a):(b) #define min1(a,b) (a)<(b)?(a):(b) #define pi acos(-1.0) #define eps 1e-8 #define me(a,b) memset(a,b,sizeof(a)) long long a[500009]; int main() { int t; scanf("%d",&t); int n,m,z,l; while(t--) { scanf("%d%d%d%d",&n,&m,&z,&l); a[1]=0; long long sum=0; for(int i=2;i<=n;i++) { a[i]=(a[i-1]*m+z)%l; sum=sum^a[i]; } // for(int i=2;i<=n;i++) // for(int j=2;j<=n;j++) // { // sum=sum^(a[i]+a[j]); // } printf("%I64d\n",sum*2); } return 0; }
之后看了下异或运算:
1 ^ 1=0
1 ^ 0=1
0 ^ 1=1
0 ^ 0=0
即二进制相同位 相同时值为0,不同时值为 1
在暴力 n^2的循环中 (Ai +Aj)^(Aj+Ai)==0 ,0异或任何正数都是那个正数。 所以可以舍弃它们。于是只剩下了 (Ai+Ai)^(Aj+Aj)(i!=j);即(2*Ai)^(2*Aj)==2*(Ai^Aj)。误打误撞之下对了。
异或的用途:
1):可判断两数是否相等
2): 可进行两个数的交换 swap(i,j): i=i^j; j=j^i; i=i^j; 可以这样串起来想 J=J^J^I; I=I^I^j;
3):可以实现一个数的二进制某几位的翻转,如想翻转第二,三,五位 , 直接异或 0000 0000 0001 0110 即可。
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu 5344 (多校联赛) MZL's xor --- 位运算