原题: https://cn.vjudge.net/problem/HDU-6129
题意:
有一个n长数组,m次操作,每次将当前数组转变成前缀数组。
解析:
观察m次操作后第一个数对后面每个位置的影响(异或两次等于没影响)
0: 1 0 0 0 0 0 0 0
1: 1 1 1 1 1 1 1 1
2: 1 0 1 0 1 0 1 0
3: 1 1 0 0 1 1 0 0
4: 1 0 0 0 1 0 0 0
5: 1 1 1 1 0 0 0 0
6: 1 0 1 0 0 0 0 0
7: 1 1 0 0 0 0 0 0
8: 1 0 0 0 0 0 0 0
1: 1 1 1 1 1 1 1 1
2: 1 0 1 0 1 0 1 0
4: 1 0 0 0 1 0 0 0
8: 1 0 0 0 0 0 0 0
发现在第2^k次操作后,第一个位置对间隔k+1个位置有影响,而且影响可以叠加,所以我们可以把m分成二进制位。
对于第i位(从0开始),影响间隔为i+1,设为x,发现
1的影响:1->1+x 1+x->1+2x
2的影响:2->2+x 2+x->2+2x
假设x=1
1的影响:1->2 2->3
2的影响:2->3 3->3
所以我直接从2->3就可以把1和2的影响同时继承,所以遍历维护即可
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define debug(i) printf("# %d\n",i)
int a[1000009];
int main(){
int t;scanf("%d",&t);
while(t--){
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
for(int i=0,j=1;j<=min(n,m);i++,j<<=1){
if(m&j){
for(int k=1;k<n;k++){
a[k+j]^=a[k];
}
}
}
for(int i=1;i<=n;i++){
printf("%d%c",a[i],(i==n?'\n':' '));
}
}
}