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("
");
    }
    return 0;
}
如果有错误,请指出,谢谢
原文地址:https://www.cnblogs.com/Alruddy/p/7368554.html