洛谷P4869 albus就是要第一个出场(线性基)

传送门

不知道线性基是什么东西的可以看看蒟蒻的总结

线性基居然有这性质我还不知道orz

假设$n$个数的线性基中有$k$个数,那么显然共有$2^k$个不同的异或和,而其中每一个异或和的出现次数都是$2^{n-k}$

感性理解一下的话……就是不在线性基中的每一个数字都可以被线性基中的数字表示出来从而异或之后为0,那么这些数字都可以看做0,

所以每一个异或和都可以异或上0变成自己,那么0有多少种选法呢?加上空集就是$2^{n-k}$种

然后只要算出$q$之前有多少个数就好了……

然后这个东西具体怎么算……看代码好了……

 1 //minamoto
 2 #include<iostream>
 3 #include<cstdio>
 4 using namespace std;
 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 6 char buf[1<<21],*p1=buf,*p2=buf;
 7 inline int read(){
 8     #define num ch-'0'
 9     char ch;bool flag=0;int res;
10     while((ch=getc())>'9'||ch<'0')
11     (ch=='-')&&(flag=true);
12     for(res=num;(ch=getc())<='9'&&ch>='0';res=res*10+num);
13     (flag)&&(res=-res);
14     #undef num
15     return res;
16 }
17 const int mod=10086;
18 int b[35],st[35],top,n,q,rk;
19 inline int ksm(int x,int y){
20     int res=1;
21     while(y){
22         if(y&1) (res*=x)%=mod;
23         (x*=x)%=mod,y>>=1;
24     }
25     return res;
26 }
27 void insert(int x){
28     for(int i=30;i>=0;--i)
29     if(x>>i&1){
30         if(!b[i]) return (void)(b[i]=x);
31         x^=b[i];        
32     }
33 }
34 int main(){
35 //    freopen("testdata.in","r",stdin);
36     n=read();
37     for(int i=1,x;i<=n;++i) insert(x=read());
38     q=read();
39     for(int i=0;i<=30;++i)
40     if(b[i]) st[top++]=i;
41     for(int i=0;i<top;++i)
42     if(q>>st[i]&1) rk+=1<<i;
43     printf("%d
",(1ll*rk*ksm(2,n-top)+1)%mod);
44     return 0;
45 }
原文地址:https://www.cnblogs.com/bztMinamoto/p/9715741.html