因为\(Ans<=2^{63}\)所以根据不同的\(k\)值,所有数的位数\(m\)是不一样的,\(k\)越大,\(m\)越小。
\(Ans=\sum_{i_1=1}^m\sum_{i_2=1}^m...\sum_{i_k=1}^m(2^{\sum_{j=1}^ki_j}E(\prod_{j=1}^kbit(xor(A\subset S))))\)
那么就很显然了,求出\(k\)位全都为1的概率,再乘上前面一坨鸟不拉屎的东西即可。
那么这个概率应该怎么算呢?
我们先用原来的\(n\)个数构造线性基,那么现在我们只需要用63个数就得到了原来的线性空间。
再从63个数中挑出这\(k\)位构造另一个线性基。
如果这一个新构造的线性基能表示出每一位都为1的数,那么它的概率就是\(\frac{2^{n-cnt}}{2^n}=\frac{1}{2^{cnt}}\)(其中\(cnt\)为线性基中有值的位的个数)
然后,就没有然后了。。。
注意:
- unsigned long long 坑的很
#include#define ull unsigned long longusing namespace std;int n,k,cnt;ull bit[70],need[70],c[7][7],x;struct FT{ ull x;bool be; FT operator +(FT b){ if (be&&b.be) return (FT){x+b.x+1,false}; return (FT){x+b.x,be|b.be}; }} ans;struct base{ int n; ull b[70]; void init(int len){ n=len; memset(b,0,sizeof(b)); } void insert(ull x){ for (int i=n;i>=0&&x;i--) if (x>>i&1) if (b[i]) x^=b[i]; else {b[i]=x;break;} } bool check(ull x){ ull res=0; for (int i=n;i>=0;i--){ if (!b[i]) continue; if ((x>>i&1)^(res>>i&1)) res^=b[i]; } return res==x; }} B,calc;inline ull read(){ ull res=0;bool bo=0; char c; while (((c=getchar())<'0'||c>'9')&&c!='-'); if (c=='-') bo=1; else res=c-48; while ((c=getchar())>='0'&&c<='9') res=(res<<3)+(res<<1)+(c-48); return bo?~res+1:res;}void Calc(){ calc.init(cnt-1); for (int i=0;i<=B.n;i++){ if (!B.b[i]) continue; int x=0; for (int j=1;j<=cnt;j++) x|=(B.b[i]>>bit[j]&1)<<(j-1); calc.insert(x); } if (!calc.check((1< =0) for (int i=1;i<=power;i++) val.x<<=1; else for (int i=1;i<=-power;i++){ if (val.x&1) val.be=true; val.x>>=1; } ans=ans+val;}void dfs(int now,int rest){ if (now==B.n+1){ if (k==rest) Calc(); return; } for (int i=0;i<=k-rest;i++){ if (i) bit[++cnt]=now,need[cnt]=i; dfs(now+1,rest+i); if (i) --cnt; }}int main(){ scanf("%d%d",&n,&k); for (int i=1;i<=n;i++){ x=read(); for (int j=63;j>=0;j--) if (x>>j&1) {B.n=max(B.n,j);break;} B.insert(x); } for (int i=0;i<=k;i++) c[i][0]=1; for (int i=1;i<=k;i++) for (int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; dfs(0,0); cout<