题意:
给出 n,m , 和 a1,a2.........an
每次操作都会有,bi=a1^a2^a3^...ai ('^'为异或)
求m次操作后的序列
思路:
比赛的时候一直在想找规律,发现了循环,就觉得这是正确方向,最后可以在O(n)的复杂度,知道m后bi由那些数异或而成,这时才发现即使知道了也要O(n2)的遍历才可以得出最后的序列,这时发现方向错了。。。。期间队友还提过组合数判断奇偶。。。。我居然反对了。。。。。我的锅我的锅。。。。
赛后补题
这时才想到,正确的方向应该是看某个数对答案序列的那些元素有贡献
我们可以轻易的把5X5的表手打出来
10000 10000 10000 1 0 0 0 0
01000 10000 21000 3 1 0 0 0
00100 10000 32100 6 3 1 0 0
00010 10000 43210 10 6 3 1 0
00001 10000 54321 15 10 6 3 1
我们从这几个可以看出每一行的系数 都是下一行的左移动一格
而每个最后一行我们都可以轻易的手打出表来,其实数学思维强的可能已经看来了
1 1 1 1 1 1 / 1 / 1 / 1 / 1 c0,0 / c1,1 / c,2,2 / c3,3 / c4,4
1 2 3 4 5 /1 / 2 / 3 / 4 / 5 / c1,0 / c2,1 / c3,2 / c4,3 / c5,4
1 3 6 10 15 /1 / 3 / 6 / 10 / 15 / c2,0 / c3,1 / c4,2 / c5,3 / c6,4
1 4 10 20 35 /1 / 4 / 10 / 20 / 35 /c3,0 / c4,1 / c5,2 / c6,3 / c7,4
1 5 15 35 70 / 1 / 5 / 15 / 35 / 70 /c4,0 / c5,1 / c6,2 / c7,3 /
我们发现每个数都是它上面的数和左边的数之和,一个杨辉三角,组合数
m次过后 ,假设 j=i+t 那么 i对j的贡献就是C m+t , t 次
刚刚才学到C(n, m)为奇数等价于n & m == m
我们遍历t(0~n)
根据C m+t , t是否为奇数来判断是否 有 对于 每个 (j>i) ans[j]^=a[j-t]
#include<bits/stdc++.h>
#define N 200009
using namespace std;
long long a[N],ans[N];
int main()
{
int T,n,m,x,y;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",a+i);
ans[i]=a[i];
}
if(m!=0)
{
m--;
for(int i=1;i<n;i++)
{
x=i;
y=m+i;
if((x&y)==x)
{
for(int j=i+1;j<=n;j++)
ans[j]^=a[j-i];
}
}
}
for (int i = 1; i <=n; i++)
printf("%lld%c", ans[i], " \n"[i==n]);
}
return 0;
}