【BZOJ2844】albus就是要第一个出场,线性基

来源:互联网 发布:程序员视频教程 编辑:程序博客网 时间:2024/05/23 01:20

Time:2016.08.29
Author:xiaoyimi
转载注明出处谢谢



传送门
喜闻乐见的线性基乱搞题
如果n个数消出m个线性基,那么这n个数能异或出的值有2m
这个很显然,但还有个很神奇的性质
2m种值各会出现2nm
这就很简单了是不是啊
枚举x的每个二进制位
sum[i]表示第1-i位上的线性基个数,m表示n个数总共的线性基个数
如果当前位i为1,那么ans就要加上2nm+sum[i1]
第i位上的线性基不能算,所以从i-1位上开始算起,共2sum[i1]种线性基,每种2nm
复杂度就是求线性基的复杂度O(31n)
代码:

#include<cstdio>#define mo 10086#define M 100003using namespace std;int n,x,sum;int a[M],lb[32];int qr(int x,int y){    int t=1;    for (;y;y>>=1,x=x*x%mo)        if (y&1) t=t*x%mo;    return t;}int in(){    int t=0;char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9') t=(t<<3)+(t<<1)+ch-48,ch=getchar();    return t;}main(){    n=in();     for (int i=1;i<=n;++i) a[i]=in();    x=in();    for (int j=1;j<=n;++j)        for (int i=30;i>=0;--i)            if (a[j]>>i&1)                if (!lb[i])                     {lb[i]=a[j];++sum;break;}                else                    a[j]^=lb[i];    int ans=1,tt=sum;    for (int i=30;i>=0;--i)    if (lb[i])    {        --sum;        if (x>>i&1)            ans=(ans+qr(2,sum+n-tt))%mo;    }    printf("%d\n",ans);}
0 0
原创粉丝点击