原题链接:
HDU-6129
大意:
给一个序列
a[i]
对其进行
m
次操作,每次操作得到一个新数列
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
Limits:
T: 5
n: 2e5
m:1e9
a[i]:2^30-1
思路:
打手表找规律,或者是慢慢分析,得到一个组合数。 第 m 次操作后 b[i] 的值与 aj j<=i 值都有对应关系。
对应组合数为
化简一下:
只要考虑对应组合数奇偶即可。而组合数的奇偶性判断,参照 Lucas定理,可得
只要满足 m 内二进制位上每个 1 的位置,对应的都是 n 的二进制位上的子集。 即为奇数
具体实现很简单: if((n&m)==m) return true;
从 ai 推到 bj 要比推 bj 时枚举 ai 要快一点。
具体实现:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
inline void read(int &x){
x=0;char p=getchar();
while(!(p<='9'&&p>='0'))p=getchar();
while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
int n,m;
const int MAXN =2e5+10;
int a[MAXN],b[MAXN];
int main() {
//freopen("1008.in","r",stdin);
//freopen("out.txt","w",stdout);
int t;
read(t);
while(t--){
mem(a,0);mem(b,0);
read(n);read(m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++){
int y=m-1,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]," \n"[i==n]);
}
}