http://acm.hdu.edu.cn/showproblem.php?pid=6129
题意:给出一个长度为n的数列,变换m次。每次变换a[i]=a[1]^a[2]^...^a[i]。输出变换m次后的数列。
题解:观察第一个数对后面每个数的贡献。
第一次变换:1 1 1 1 1
第二次变换:1 2 3 4 5
第三次变换:1 3 6 10 15
第四次变换:1 4 10 20 35
...
可以看出第x次变换的第y项cnt[x][y],第一个数对该位置的贡献为cnt[x][y-1]+cnt[x-1][y]。所以有cnt[x][y]=C(x+y-2,x-1)。
结论:
①因为只有当cnt[x][y]为奇数时才有贡献。C(n,m):当(n&m==m)时,C(n,m)为奇数。
②第一个数对第y个数奇偶与第二个数对第y+1个数的奇偶相同。
代码:
#include<bits/stdc++.h>
#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;
const int N = 2e5 + 5;
const int mod = 1000000000 + 7;
const double eps = 1e-8;
int a[N],ans[N];
int main(){
int t,n,m,x,y;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
mem(ans,0);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
x=i-1,y=i+m-2;
if((x&y)==x){
for(int j=i;j<=n;j++){
ans[j]^=a[j-i+1];
}
}
}
for(int i=1;i<n;i++){
printf("%d ",ans[i]);
}
printf("%d\n",ans[n]);
}
return 0;
}