2017多校7 -1010
找规律
列出前几项,斜着看,是杨辉三角 --> 组合数
异或满足性质:
(a oplus b oplus b = a)
所以只需要关注组合数的奇偶性就可以了
规律是
- 对于(a_1)来说,那么(m)次变换在(a_n)上的异或次数为(C_{m+n-2}^{m-1})
- 对于(a_2)来说,那么(m)次变换在(a_n)上的异或次数为(C_{m+(n-1)-2}^{m-1})
然后发现,对于(a_2)来说,就是(a_1)整体移了一位,所以如果判断出(C_{m+i-2}^{m-1}),这是(a_1)在m次变换于(a_i)处异或次数,同样上面的组合数也是(a_2)在m次变换在(a_{i+1})处的异或次数,所以可以将其都计算上去
判断奇偶性可以数组合数分子分母2的个数
代码
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <string>
#include <math.h>
#include <ctype.h>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 2e5 + 5;
int t,a[N],ans[N];
LL getx(int n, int x)
{
LL ans = 0;
while(n)
{
ans += n/x;
n /= x;
}
return ans;
}
int judge(int n, int m)
{
LL x = getx(n, 2);
LL y = getx(m, 2) + getx(n-m, 2);
return x == y;
}
int n,m;
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &n,&m);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
memset(ans, 0, sizeof(ans));
for(int i = 1; i <= n; i++)
{
int f = judge(i+m-2, m-1);
if(f)
{
int p = 1;
for(int j = i; j <= n; j++)
ans[j] ^= a[p++];
}
}
for(int i = 1; i <= n; i++)
{
if(i != 1) printf(" ");
printf("%d", ans[i]);
}
printf("
");
}
return 0;
}