hdu 6129 Just do it

题意

Just do it
有一个长度为 n 的整数序列 {an} ,对其做 m 次前缀异或和,求最终的序列。

题解

对这个过程手动模拟几行,注意不要消去,可以发现第 m 次第 i 个数的结果包含了 Cijm1+ij 次第 j 个数( ji ) 。

首先我们需要判断它的奇偶性。奇偶性相当于2进制的结果,2为质数,可以使用Lucas定理。2进制的每一位只有四种情况,其中 C10=0C00=C01=C11=1

m1 ij 的每一位展开,在第 k 位上,如果 m1 ij 都是 1,那么结果就是 0 。

从小到大枚举 k ,表示 ij 的第 k 位为 1,若 m1 的第 k 位不为 1,那么直接更新a序列本身。也就是说,每次只用满足 ij=2k a[j] 更新 a[i] ,然而此时的 a[j] 已经被 k 0k1 更新过了,所以相当于考虑了 ij 0k 位的所有情况。

代码

#include 
using namespace std;

const int N=2e5+5;
int a[N];

int main()
{
    int T,n,m;
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) {
            scanf("%d",a+i);
        }
        int k=1;m--;
        while (kif ((m&1)==0) {
                for (int i=n;i>k;i--) {
                    a[i]^=a[i-k];
                }
            }
            m>>=1;k<<=1;
        }
        for (int i=1;i<=n;i++) {
            printf("%d%c",a[i]," \n"[i==n]);
        }
    }
    return 0;
}

你可能感兴趣的:(hdu 6129 Just do it)