【清华集训2014】玛里苟斯(数学 线性基)
original link - http://uoj.ac/problem/36
題意:
有一個多重集S={a1,a2,...an}S=\{a_1,a_2,...a_n\}S={a1?,a2?,...an?},你會從中隨機選出一個集合S={b1,b2,...bk}S=\{b_1,b_2,...b_k\}S={b1?,b2?,...bk?},這個集合的異或為XXX,求XkX^kXk的期望。
解析:
先考慮k=1k=1k=1的情況,如果一個二進制位bbb在某個數內出現過,那么bbb出現在最后XXX里的概率就固定為12\frac{1}{2}21?。
這個很好證明,加入一個含有bbb的數前,設不出現的概率為ppp,出現的概率為1?p1-p1?p,那么12\frac{1}{2}21?的概率加入bbb,12\frac{1}{2}21?的概率不加入。算一下之后不出現的概率和出現的概率都變為12\frac{1}{2}21?。
那么也就是說答案為所有出現過的二進制位之和除以二。
k=2k=2k=2時,XXX的平方可以寫成(bk...b1b0)(bk...b1b0)=bkbk+bkbk?1+...bkb1+...b1b1(b_k...b_1b_0)(b_k...b_1b_0)=b_kb_k+b_kb_{k-1}+...b_kb_1+...b_1b_1(bk?...b1?b0?)(bk?...b1?b0?)=bk?bk?+bk?bk?1?+...bk?b1?+...b1?b1?。所以我們可以計算每兩個二進制位這種組合的期望,即XXX中同時存在bi,bjb_i,b_jbi?,bj?的概率是多少。
原先的每個數,這兩位可能的情況為:00,01,10,1100,01,10,1100,01,10,11。設其概率分別為a,b,c,1?a?b?ca,b,c,1-a-b-ca,b,c,1?a?b?c,其中a+b=12,a+c=12,b=ca+b=\frac{1}{2},a+c=\frac{1}{2},b=ca+b=21?,a+c=21?,b=c,推一推就會發現:
- 如果只有000000,顯然無貢獻;
- 只有00,1100,1100,11時,和k=1k=1k=1同為12\frac{1}{2}21?;
- 若存在010101或101010,為14\frac{1}{4}41?。
k>2k>2k>2時,由于說明答案小于2632^{63}263,所以原先的aia_iai?不會很大,頂多220+k2^{20+k}220+k,所以我們可以直接枚舉所有可能的XXX(用線性基),將XkX^kXk除上總方案數加入答案即可(因為所有情況的概率相同)。
但是先加起來再除會爆,得操作一下。若最后的狀態數為allallall,用兩個變量維護Xk/allX^k/allXk/all和Xk%allX^k\%allXk%all即可。
代碼:
/** Author : Jk_Chen* Date : 2019-09-25-16.41.04*/ #include<bits/stdc++.h> using namespace std; #define LL unsigned long long #define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++) #define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--) #define mmm(a,b) memset(a,b,sizeof(a)) #define pb push_back #define pill pair<int, int> #define fi first #define se second #define debug(x) cerr<<#x<<" = "<<x<<'\n'; const LL mod=1e9+7; const int maxn=1e5+9; const int inf=0x3f3f3f3f; LL rd(){ LL ans=0; char last=' ',ch=getchar();while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();if(last=='-')ans=-ans; return ans; } /*_________________________________________________________begin*/const int Len=64; struct linear_Bace{LL a[Len];LL& operator [](int idx){return a[idx];}LL operator [](int idx)const{return a[idx];}void insert(LL val){for(int i=Len-1;i>=0;i--){if((val>>i)&1){if(!a[i]){a[i]=val;break;}val^=a[i];}}}bool find(LL val){for(int i=Len-1;i>=0;i--){if((val>>i)&1){if(a[i]){val^=a[i];}elsereturn 0;}}return 1;} }LB;bool bit[70]; bool dBit[70][70];int main(){int n=rd(),K=rd();rep(i,1,n){LL a=rd();if(K>2){LB.insert(a);}rep(j,0,63){if(a&(1ull<<j)){bit[j]=1;rep(k,j+1,63){if(!(a&(1ull<<k))){dBit[j][k]=dBit[k][j]=1;}}}else{rep(k,j+1,63){if(a&(1ull<<k)){dBit[j][k]=dBit[k][j]=1;}}}}}if(K==1){LL sum=0;rep(i,0,63){if(bit[i])sum+=1ull<<i;}printf("%llu",sum>>1);puts((sum&1)?".5":"");}else if(K==2){LL sum=0;rep(i,0,40){if(!bit[i])continue;rep(j,0,40){if(!bit[j])continue;if(i==j){sum+=1ull<<(i+j);}else if(dBit[i][j]){sum+=1ull<<(i+j-1);}else{sum+=1ull<<(i+j);}}}printf("%llu",sum>>1);puts((sum&1)?".5":"");}else{LL sum=0,sumr=0;int ct=0;LL sta[100];rep(i,0,63){if(LB[i]){sta[++ct]=LB[i];}}rep(S,0,(1<<ct)-1){LL val=0;rep(j,1,ct){if((S>>j-1)&1)val^=sta[j];}// val^KLL div=0,remd=1;rep(_,1,K){div*=val,remd*=val;div+=remd>>ct,remd&=(1ull<<ct)-1;}sum+=div,sumr+=remd;}sum+=sumr>>ct,sumr&=(1ull<<ct)-1;printf("%llu",sum);puts(sumr?".5":"");}return 0; }總結
以上是生活随笔為你收集整理的【清华集训2014】玛里苟斯(数学 线性基)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习CV文章整理
- 下一篇: 卸载方方格子