HDU 6129 暴力,规律
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("\n");
}
return 0;
}
如果有错误,请指出,谢谢