Just do it
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 836 Accepted Submission(s): 478
Total Submission(s): 836 Accepted Submission(s): 478
Problem Description
There is a nonnegative integer sequence
a1...n
of length
n
. HazelFan wants to do a type of transformation called prefix-XOR, which means
a1...n
changes into
b1...n
, where
bi
equals to the XOR value of
a1,...,ai
. He will repeat it for
m
times, please tell him the final sequence.
Input
The first line contains a positive integer
T(1≤T≤5)
, denoting the number of test cases.
For each test case:
The first line contains two positive integers n,m(1≤n≤2×105,1≤m≤109) .
The second line contains n nonnegative integers a1...n(0≤ai≤230−1) .
For each test case:
The first line contains two positive integers n,m(1≤n≤2×105,1≤m≤109) .
The second line contains n nonnegative integers a1...n(0≤ai≤230−1) .
Output
For each test case:
A single line contains n nonnegative integers, denoting the final sequence.
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次前缀异或和。
解题思路:写一写前前几次的结果,观察规律
(以n=5,m=5为例)
An上面的系数代表这个数异或了几次。
把每一次的第i项a1异或的次数拿出来得到
1 1 1 1 1
1 2 3 4 5
1 3 6 10 15
1 4 10 20 35
1 5 15 35 70
.............................
发现斜着来的话是一个杨辉三角,第x次变换的第y项则系数为C(x+y-2,y-1)
知识点:1.一个数异或偶数次自己为0。2.一个数异或奇数次自己为其本身。3.一个数异或0为它本身。
也就是说当异或的次数为偶数时相当于没有异或,为奇数时相当于其本身,那么我们把每一次异或的系数求出判断它的奇偶性,并进行计算。比如上图m=5,n=5.我们要求第m次一伙的第1项时,算出C(4,0)=1,为奇数都有1这个系数,b[1]~b[5](最终要求的)异或上a[1]~a[5].第二项C(5,1)=5,为奇数,b[2]~b[5]分别异或a[1]~a[4],.............一直按这个规律求下去。
那么下面有一个问题就是说如何判断C(K,S)为奇数还是偶数,算出来,嗯,可以直观想法但当K,S很大时会爆的。有一个结论:如果K&S==S,那么C(K,S)为奇数。网上有一些证明,看懂了一点结合自己的看法证了一下,下面为证明过程。
证明:
对于给定C(K,S),检查n中2因子的个数与S和(K-S)中2因子个数和的关系,假设K!中2因子个数为a,S!中2因子个数为b,(K-S)!中2因子个数为c,则显然有a>=(b+c);并且当a==b+c时,一定为奇,否则为偶。题意转化为求a和b+c。
K!中含有2因子的个数等于(K-它的二进制形式中1的个数) 先证明这个小结论。
1.当K等于1时显然成立。
2.假设当K=P时也成立,即P=P二进制形式中1的个数(设为Pe)+P!中含有2因子的个数(设为Pg)。
3.当P为偶数时,P+1为奇数,那么(P+1)!中含有2因子的个数就为Pg,而(P+1)二进制形式中的1的个数为Pe+1.
所以,P+1=(P+1)二进制形式中1的个数(设为Pe1)+(P+1)!中含有2因子的个数(设为Pg1)
当P为奇数的时候,P+1假设进位为t(比如1001+1--->1010进位就为1,而1011111+1--->1100000进位为5)发现P+1二进制中1的个数比P二进制中1的个数少了t-1个,并且(P+1)中2因子的个数比P中2因子的个数多了t个(因为是奇数,所以为0),1011111----0个,1100000----2^5+2^6-----2^5(1+2^6)
因为我们假设P=Pe+Pg,那么P+1=Pe+Pg+1.而Pg1=Pg+t,Pe1=Pe-t+1,则P+1=Pe1+t-1+Pg1-t+1.即P+1=Pe1+Pg1.
由数学归纳法的得原结论:K!中含有2因子的个数等于(K-它的二进制形式中1的个数)成立。
a=K-K二进制形式中1的个数,b=S-K二进制形式中1的个数 ,c=K-S -(K-S)二进制形式中1的个数。
如果a=b+c(即C(K,S)为奇数)那么 K-K二进制形式中1的个数=S-S二进制形式中1的个数+K-S-(K-S)二进制形式中1的个数。化简得:
K二进制形式中1的个数-S二进制形式中1的个数=(K-S)二进制形式中1的个数。由此条件可得K&S==S即判断C(K,S)为奇数。
举个例子:K=1001101110
S= 1101010 那么K-S ->1000000100
这个时候 K二进制形式中1的个数-S二进制形式中1的个数=(K-S)二进制形式中1的个数 等价于 K&S==S 反之则不成立,有兴趣的可以自己模拟一下。
AC代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
int a[2050000];
int b[2050000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(b,0,sizeof(b));
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
for(int i=1; i<=n; i++)
{
int y=i-1;
int x=i+m-2;
if((x&y)==y)///判断为奇数
{
for(int j=i; j<=n; j++)
b[j]^=a[j-i+1];
}
}
for(int i=1; i<=n; i++)
{
printf("%d%c",b[i],i==n?'\n':' ');
}
}
return 0;
}