BZOJ 3811: 玛里苟斯 线性基

https://www.lydsy.com/JudgeOnline/problem.php?id=3811

老夫线性基出师啦!(没有)

https://blog.sengxian.com/algorithms/linear-basis 感谢cydiater给的网址(我怎么不自己百度啊伸手党真恶心呸)

求期望,指数1直接每一位取一个二分之一就阔以了。

指数2可以两位两位结合然后取二分之一或者四分之一(把二维变成两个一维相乘,如果某两位每次都是一起出现,那么有贡献的概率就是1/2,如果有一次及以上不一起出现,有贡献的概率就是1/4),指数2这里我的代码在找某位的1存在的时候直接找的原数,找线性基更快,但是找两位的1是否一定一起出现只能用原数。

指数3以上的话线性基的位数就很少了可以直接搜,为了不爆ull有一个特殊的技巧(看代码)(因为最后要除2^位数那么把小于2^位数的存一下,大于2^位数的存一下)。

出现小数的话小数只能为.5,从指数1的情况可以推广。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define LL unsigned long long
 8 const int maxn=100005;
 9 int n,m,f=0,mx;
10 LL b[65]={},c[65]={},a[maxn]={};
11 inline void init(LL x){
12     for(int i=mx;i>0;i--){
13         if(x&c[i]){
14             if(!b[i]){
15                 for(int j=1;j<i;++j)if((x>>(j-1))&1)x^=b[j];
16                 for(int j=i+1;j<=60;++j)if((b[j]>>(i-1))&1)b[j]^=x;
17                 b[i]=x;break;
18             }
19             x^=b[i];
20             if(!x)f=1;
21         }
22     }
23 }
24 int main(){
25     LL x,y;
26     scanf("%d%d",&n,&m);
27     c[1]=1; for(int i=2;i<=32;++i)c[i]=c[i-1]*2;
28     if(m==1){
29         x=0;
30         for(int i=1;i<=n;++i){scanf("%llu",&y);x|=y;}
31         printf("%llu",x/2);
32         if(x&1)printf(".5");
33         printf("\n");
34     }
35     else if(m==2){
36         LL ans=0,fla=0;mx=32;
37         for(int i=1;i<=n;++i){scanf("%llu",&a[i]);init(a[i]);}
38         for(int i=1;i<=mx;++i){
39             for(int j=1;j<=mx;++j){
40                 bool f=0;
41                 for(int k=1;k<=n;++k)if((a[k]>>(i-1))&1){f=1;break;}
42                 if(!f)continue;
43                 f=0;
44                 for(int k=1;k<=n;++k)if((a[k]>>(j-1))&1){f=1;break;}
45                 if(!f)continue;
46                 f=0;
47                 for(int k=1;k<=n;++k)if(((a[k]>>(i-1))&1)!=((a[k]>>(j-1))&1)){f=1;break;}
48                 if(i==1&&j==1)fla++;
49                 else if(((i==1&&j==2)||(i==2&&j==1))&&f)fla++;
50                 else{
51                     if(f) ans+=((LL)1<<(i+j-4));
52                     else ans+=((LL)1<<(i+j-3));
53                 }
54             }
55         }
56         ans=ans+fla/2;printf("%llu",ans);
57         if(fla&1)printf(".5");
58         printf("\n");
59     }
60     else{
61         LL ans=0,fla=0;int siz=0;mx=24;
62         for(int i=1;i<=n;++i){scanf("%llu",&x);init(x);}
63         for(int i=1;i<=mx;++i)if(b[i])b[++siz]=b[i];
64         LL num=((LL)1<<siz);
65         for(LL i=1;i<num;++i){
66             LL tem=0;
67             for(int j=0;j<siz;++j)if(i&((LL)1<<j))tem^=b[j+1];
68             LL aa=0,bb=1;
69             for(int j=0;j<m;++j){
70                 aa*=tem;bb*=tem;
71                 aa+=bb/num;bb&=(num-1);
72             }
73             ans+=aa;fla+=bb;
74             ans+=fla/num;fla&=(num-1);
75         }
76         printf("%llu",ans);
77         if(fla)printf(".5");
78         printf("\n");
79     }
80     return 0;
81 }
View Code

 

 

 

posted @ 2018-04-15 21:23  鲸头鹳  阅读(145)  评论(0编辑  收藏  举报