第一次写线性基,借鉴了PoPoQQQ大神的程序
所以主要做法就不说了,就说一说后面$ans$到底具体是什么
因为我们求线性基是从大到小求所以数字会递减
首先我们像数位dp一样从大到小枚举now,确认一次最多能取多少
因为如果第$i$个数可以取,那么后面的所有线性基都可以在不取当前值的情况下一次取完,所以总共的取法数$ans+=Qpow(2,n-i)$
如果曾经取过一些线性基,那么总取法要加上1(因为之前统计的是绝对<Q的,所以要加上当前的一个)
然后我们得知还有m个自由基,也就是可以经过某些排列组合后进行抵消(等于没用)
所以我们直接确定每个数是否取就行了,所以总共的取法数$ans*=Qpow(2,m)$
最后加上1是因为0也是一种方案
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=100005,P=10086; int n,a[N],Q,m,ans; inline void Read(int &x){ static char ch; while((ch=getchar())<'0' || ch>'9'); x=ch-'0'; while((ch=getchar())>='0' && ch<='9')x=(x<<3)+(x<<1)+ch-'0'; } inline void Gauss(){ int t=0,r; for(register int i=1<<30;i;i>>=1){ for(register int j=t+1;(r=j)<=n;j++)if(a[j]&i)break; if(r==n+1)continue; swap(a[r],a[++t]); for(register int j=1;j<=n;j++)if(j!=t && (a[j]&i))a[j]^=a[t]; } m=n-t; n=t; } inline int Qpow(int x,int y){ int z=1; while(y){ if(y&1)z=z*x%P; x=x*x%P; y>>=1; } return z; } int main(){ freopen("2844.in","r",stdin); freopen("2844.out","w",stdout); Read(n); for(register int i=1;i<=n;i++)Read(a[i]); Gauss(); Read(Q); int nw=0; for(register int i=1;i<=n;i++){ if((nw^a[i])<Q)nw^=a[i],ans=(ans+Qpow(2,n-i))%P; } if(Q)ans++; ans=ans*Qpow(2,m)%P+1; printf("%d\n",ans%P); return 0; }