[HDU6129]Just do it

Description
There is a nonnegative integer sequence (a_{1...n}) of length (n). HazelFan wants to do a type of transformation called prefix-XOR, which means (a_{1...n}) changes into (b_{1...n}), where (b_i) equals to the XOR value of (a_1,...,a_i). He will repeat it for m times, please tell him the final sequence.

Input
The first line contains a positive integer (T(1leqslant Tleqslant 5)), denoting the number of test cases.
For each test case:
The first line contains two positive integers (n,m(1leqslant nleqslant 2×10^5,1leqslant mleqslant 10^9)).
The second line contains (n) nonnegative integers (a_{1...n}(0leqslant a_ileqslant 2^{30}−1)).

Output
For each test case:
A single line contains (n) nonnegative integers, denoting the final sequence.

Sample Input

2
1 1
1
3 3
1 2 3

Sample Output

1
1 3 1

显然,直接暴力做m次前缀异或和是不可行的,我们先用变量列几个数出来找一下规律

(记(otimes)为异或操作,(a^k)表示有(k)(a)进行异或操作)

次数 (a) (b) (c) (d)
1 (a) (aotimes b) (aotimes botimes c) (aotimes botimes cotimes d)
2 (a) (a^2otimes b) (a^3otimes b^2otimes c) (a^4otimes b^3otimes c^2otimes d)
3 (a) (a^3otimes b) (a^6otimes b^3otimes c) (a^{10}otimes b^6otimes c^3otimes d)

可以发现,对于表格中的某个位置(A[i][j])而言,其可以写成(A[i][j]=A[i-1][j]otimes A[i][j-1]),这个形式十分类似于杨辉三角,而将整个表格顺时针旋转45°后,单独查看某个变量的系数,其就是杨辉三角

稍加推理可得,对于数列中第(i)个数,其在做完(m)次操作后,对第(j)位数((i<j))的贡献是(inom{(m-1)+(j-i)}{m-1})

但直接计算的话肯定会超时。我们注意到这是异或操作,故只有奇数次的贡献才是有效的,根据组合数奇偶性定理可得,当(n & k=k)时,(inom{n}{k})才为奇数

将该定理代入之前的式子,很容易得到((m-1) & (j-i)=0),即((j-i)_2)中1的位置必定是((m-1)_2)中0的位置

我们再按照01背包的思路,每次枚举出一个((m-1)_2)的0的位置,可得到(2^k((m-1) & 2^k=0)),再将每个数的贡献累加到其之后(2^k)的位置上的数即可

/*program from Wolfycz*/
#include<map>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define ll_inf 1e18
#define MK make_pair
#define sqr(x) ((x)*(x))
#define pii pair<int,int>
#define int_inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
	static char buf[1000000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline T frd(T x){
	int f=1; char ch=gc();
	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
template<typename T>inline T read(T x){
	int f=1; char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x<0)	putchar('-'),x=-x;
	if (x>9)	print(x/10);
	putchar(x%10+'0');
}
const int N=2e5;
int A[N+10];
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read(0);
	while (T--){
		int n=read(0),m=read(0)-1;
		for (int i=1;i<=n;i++)	A[i]=read(0);
		for (int j=30;~j;j--){
			if (m&(1<<j))	continue;
			for (int i=n;i>1<<j;i--)
				A[i]^=A[i-(1<<j)];
		}
		for (int i=1;i<=n;i++){
			printf("%d",A[i]);
			putchar(i==n?'
':' ');
		}
	}
	return 0;
}
作者:Wolfycz
本文版权归作者和博客园共有,欢迎转载,但必须在文章开头注明原文出处,否则保留追究法律责任的权利
原文地址:https://www.cnblogs.com/Wolfycz/p/14930372.html