HDU 6129 Just do it【杨辉三角+思维+Lucas定理】

来源:互联网 发布:网络攻击防御软件 编辑:程序博客网 时间:2024/05/23 19:14

题目链接

题意:a1an这n个数,每次操作使ai=a1^a2^…^ai,把这个操作重复m次,求最后所得的序列。

显然异或两次就等于没异或。考虑每个数在每一次操作后对每个数异或的次数,可以得到下面的矩阵。

1111dp[m][1]1234dp[m][2]13610dp[m][3]1ndp[3][n]dp[4][n]dp[m][n]

其中第i行就是经过i次操作后所得的序列。

多写几个数可以发现规律,这是一个杨辉三角。(比赛时没想到这点)

杨辉三角第n行的第m个数等于Cm1n1。对这题来说,单独考虑每个ai,最后的数dp[m][i]是在杨辉三角中的第i+m1行的第i个数,就等于Ci1i+m2,而因为异或两次等于没异或,所以我们只要判断奇偶就可以了。

Cmn为奇数当且仅当(n&m)==m

还有一个Lucas定理可以用来判断C(n,m)%p的值,顺便提一下。

想到这几点,后面的就很好写了。

#include <bits/stdc++.h>using namespace std;int a[200010];int ans[200010];int n,m;int T;int main(){    scanf("%d",&T);    while (T--){        scanf("%d %d",&n,&m);        memset(ans,0,sizeof(ans));        for (int i=1;i<=n;i++)  scanf("%d",&a[i]);        for (int i=1;i<=n;i++){            int x=i+m-2;            int y=i-1;            if ((x&y)==y){                for (int j=i;j<=n;j++){                    ans[j]^=a[j-i+1];                }            }        }        for (int i=1;i<=n;i++){            if (i==1)   printf("%d",ans[i]);            else    printf(" %d",ans[i]);        }        putchar('\n');    }    return 0;}
原创粉丝点击