线性基 刷题记录

Posted jiecaoer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性基 刷题记录相关的知识,希望对你有一定的参考价值。

HDU3949 XOR

  • 线性基板子题
  • 给定一些数
  • 求这些数能通过异或得到的第k大的值。
  • 代码:
    技术图片
     1 #include <bits/stdc++.h>
     2 #define nmax 10010
     3 
     4 using namespace std;
     5 typedef long long ll;
     6 ll a[nmax],b[70],k[70]; //k[i] 第i小的数
     7 int n,q;
     8 
     9 int main()
    10     //freopen("owo.in","r",stdin);
    11     int T;
    12     cin>>T;
    13     for (int cas=1; cas<=T; cas++) 
    14         memset(b,0,sizeof(b));
    15         memset(k,0,sizeof(k));
    16         printf("Case #%d:\n",cas);
    17         scanf("%d",&n);
    18         for (int i=0; i<n; i++) 
    19             scanf("%lld",&a[i]);
    20             //求线性基
    21             for (int j=61; j>=0; j--) 
    22                 if(a[i]&(1LL<<j))
    23                     if(b[j]) a[i]^=b[j];
    24                     else  b[j]=a[i]; break; 
    25                 
    26             
    27         
    28         //往上回代,顺便统计个数
    29         int cnt=0;
    30         for (int i=0; i<=61; i++) if(b[i]) 
    31                 k[cnt]=b[i];
    32                 cnt++;
    33                 for (int j=i+1; j<=61; j++) if(b[j]&(1LL<<i)) b[j]^=b[i];
    34         
    35         ll mmax=(1LL<<cnt)-1;
    36         scanf("%d",&q);
    37         ll inq;
    38         bool flag=false;
    39         if(cnt<n) flag=true;
    40         for (int j=0; j<q; j++) 
    41             scanf("%lld",&inq);
    42             if(flag) inq--;
    43             if(inq>mmax) cout<<-1<<endl;
    44             else 
    45                 ll ans=0;
    46                 for (int i=0; (1LL<<i)<=inq; i++) if((1LL<<i)&inq) ans^=k[i];
    47                 printf("%lld\n",ans);
    48             
    49         
    50     
    51     return 0;
    52 
    quq

     

BZOJ 2115: [Wc2011] Xor

  • 题意,一个无向图,节点编号1~n,求从1到n的一条路径,边和点可以经过多次,求经过边的权值xor最大的那一条路径
  • 题解:随便找一条路径从1~n的,然后可以发现任意路径都可以表示为在这条路径上走环,所以找出所有的环
  • 然后就是在所有的环里找和主路径异或最大的
  • 找所有的环用dfs
  • 代码:
    技术图片
     1 #include <bits/stdc++.h>
     2 #define nmax 50010
     3 #define mmax 100010
     4  
     5 using namespace std;
     6 typedef long long ll;
     7 int head[nmax]=0,d[nmax]=0;  //被vis到的顺序
     8 ll a[nmax+mmax],tmp[nmax],b[70]=0;
     9 int n,m,idx=0,idxa=0;  //idza是记录环的数量
    10 struct edge
    11     int v,ne;
    12     ll w;
    13 e[mmax*2];
    14  
    15 inline void addedge(int u,int v,ll w)
    16     idx++;
    17     e[idx].v=v;
    18     e[idx].w=w;
    19     e[idx].ne=head[u];
    20     head[u]=idx;
    21 
    22  
    23 void build()
    24     cin>>n>>m;
    25     int a,b;   ll c;
    26     for (int i=0; i<m; i++) 
    27         scanf("%d%d%lld",&a,&b,&c);
    28         addedge(a,b,c);
    29         addedge(b,a,c);
    30     
    31 
    32  
    33 void dfs(int u,int cnt)
    34     d[u]=cnt;
    35     for (int i=head[u]; i; i=e[i].ne)
    36         int v=e[i].v;  ll w=e[i].w;
    37         if(d[v]>d[u]) continue;
    38         if(d[v])
    39             ll x=tmp[v]^tmp[u]^w;  //这个环的xor值
    40             //cout<<"now u= "<<u<<" v= "<<v<<"  and x= "<<x<<endl;
    41             if(x) a[++idxa]=x;  //如果是0就舍弃
    42         else 
    43             tmp[v]=tmp[u]^w;  //在dfs(u)之前,u的tmp值已经算出
    44             dfs(v,cnt+1);
    45         
    46     
    47 
    48  
    49 void xxj()
    50     for (int i=1; i<=idxa; i++) for (int j=63; j>=0; j--) if((1LL<<j)&a[i])
    51         if(b[j]) a[i]^=b[j];
    52         else  b[j]=a[i]; break; 
    53     
    54     ll ans=tmp[n];
    55     for (int i=63; i>=0; i--) ans=max(ans,ans^b[i]);
    56     printf("%lld\n",ans);
    57 
    58  
    59 int main()
    60     build();
    61     dfs(1,1);
    62     xxj();
    63     return 0;
    64 
    owo

     

以上是关于线性基 刷题记录的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题--点滴记录004

LeetCode刷题 -- 双指针篇 -- 三数之和

LeetCode刷题 -- 双指针篇 -- 三数之和

PTA刷题记录

算法刷题记录

bmzctf 刷题记录 zonghe