zoukankan      html  css  js  c++  java
  • 学习线性基

    参考博客:

    https://blog.csdn.net/a_forever_dream/article/details/83654397

    https://ouuan.github.io/%E7%BA%BF%E6%80%A7%E5%9F%BA%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/

    https://blog.sengxian.com/algorithms/linear-basis


    线性基性质:

    1、原序列里面的任意一个数都可以由线性基里面的一些数异或得到。
    2、线性基里面的任意一些数异或起来都不能得到0 00
    3、线性基里面的数的个数唯一,并且在保持性质一的前提下,数的个数是最少的


    解决的问题

    1、最大异或和

    2、第 kk 大异或和/异或和是第几大

    3、求所有异或值的和


    【例题】P3812 【模板】线性基

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int M = 70;
     5 typedef struct LB{
     6     ll d[M];
     7     void Insert( ll x ){
     8         ll t = x ;
     9         for(ll i=62;i>=0;i--){
    10             if( (x & (1ll<<i))  ){
    11                 if( d[i] ){
    12                     x ^= d[i];
    13                 }else {
    14                     d[i] = x;
    15                     break;
    16                 }
    17             }
    18         }
    19     }
    20     ll Max(){
    21         ll ans = 0 ;
    22         for(int i=62;i>=0;i--){
    23             ans = max( ans , ans ^ d[i] );
    24         }
    25         return ans;
    26     }
    27 }LB;
    28 LB s;
    29 int n;
    30 ll a[M];
    31 int main()
    32 {
    33     scanf("%d",&n);
    34     for(int i=1;i<=n;i++){
    35         scanf("%lld",&a[i]);
    36         s.Insert(a[i]);
    37     }
    38 
    39     return printf("%lld
    ",s.Max())*0;
    40 }
    View Code

    【例题】P4570 [BJWC2011]元素

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int M = 70;
     5 const int N = 1e3+10;
     6 typedef struct Node {
     7     ll No;
     8     ll val;
     9     bool operator < ( const Node & rhs) const {
    10         return val > rhs.val;
    11     }
    12 }Node ;
    13 Node a[N];
    14 typedef struct LB{
    15     ll d[M];
    16     bool Insert( ll x ){
    17         for(int i=62;i>=0;i--){
    18             if( (1ll<<i) & x ){
    19                 if(d[i]){
    20                     x ^= d[i];
    21                 }else{
    22                     d[i] = x ;
    23                     return true;
    24                 }
    25             }
    26         }
    27         return false ;
    28     }
    29 
    30 }LB;
    31 LB s;
    32 int n;
    33 int main()
    34 {
    35     scanf("%d",&n);
    36     for(int i=1;i<=n;i++){
    37         scanf("%lld%lld",&a[i].No,&a[i].val);
    38     }
    39     sort( a+1 , a+1+n );
    40     ll ans = 0 ;
    41     for(int i=1;i<=n;i++){
    42         if( s.Insert(a[i].No) )
    43             ans += a[i].val;
    44     }
    45     return printf("%lld
    ",ans)*0;
    46 }
    View Code

    【例题】P3857 [TJOI2008]彩灯

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N = 100;
     5 char s[N][N];
     6 ll a[N];
     7 int n,m;
     8 struct LB{
     9     ll d[70];
    10     bool Insert( ll x ){
    11         for(int i=62;i>=0;i--){
    12             if( (x>>i)&1 ){
    13                 if(!d[i]){
    14                     d[i] = x ;
    15                     return true;
    16                 }else{
    17                     x ^= d[i] ;
    18                 }
    19             }
    20         }
    21         return false ;
    22     }
    23 }S;
    24 int main()
    25 {
    26     scanf("%d%d",&m,&n);
    27     for(int i=1;i<=n;i++){
    28         scanf("%s",s[i]);
    29     }
    30     for(int i=1;i<=n;i++){
    31 
    32         for(int j=m-1;j>=0;j--){
    33             a[i] = a[i]+ (1ll*(s[i][j]=='O')<<(m-1-j)) ;
    34         }
    35         //printf("%lld
    ",a[i]);
    36     }
    37     int k = 0 ;
    38     for(int i=1;i<=n;i++){
    39         if( S.Insert(a[i]) )
    40             k++;
    41     }
    42 
    43     ll ans = 1 ;
    44     for(int i=1;i<=k;i++){
    45         ans = (ans<<1) % 2008 ;
    46     }
    47     printf("%lld
    ",ans);
    48     return 0;
    49 }
    View Code

    【例题】P3292 [SCOI2016]幸运数字

      1 // luogu-judger-enable-o2
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<cstring>
      5 #include<algorithm>
      6 using namespace std;
      7 typedef long long ll;
      8 const int N = 20010;
      9 const int M = 60 ;
     10 
     11 template < class T >
     12 void read( T& x ){
     13     x = 0;
     14     int f = 1 ;
     15     char c = getchar() ;
     16     while(  c<'0'||c>'9' ) {
     17         if (c == '-') f = -1;
     18         c = getchar();
     19     }
     20     while( c>='0'&&c<='9' ) {
     21         x = x * 10 + c - '0';
     22         c = getchar();
     23     }
     24     x = x * f ;
     25 }
     26 inline ll max( ll x,ll y ){
     27     return x > y ? x : y ;
     28 }
     29 typedef struct Edge {
     30     int to , next ;
     31 }Edge ;
     32 Edge e[N<<1] ;
     33 int n,Q,head[N],cnt;
     34 
     35 inline void add_edge(int u,int v){
     36     e[ cnt ] = Edge{ v , head[u] };
     37     head[u] = cnt ++ ;
     38 }
     39 
     40 ll G[N],p[N][16][M+1],Ans[M+1]; //价值,树上线性基,答案线性基
     41 int up[N][16],dep[N] ; //前缀第2^k个 和 深度
     42 
     43 inline void Insert( ll x ){
     44     for(int i = M ; ~i ; i-- ){
     45         if( x >> i ){
     46             if( !Ans[i] ) { Ans[i] = x ; break ; }
     47             else x ^= Ans[i] ;
     48         }
     49     }
     50 }
     51 inline void Insert( int u , int d , ll x ){
     52     for(int i = M ; ~i ; i-- ){
     53         if( x >> i ){
     54             if( !p[u][d][i] ) { p[u][d][i] = x ; break; }
     55             else x ^= p[u][d][i] ;
     56         }
     57     }
     58 }
     59 
     60 void dfs(int u,int Fa){
     61     dep[u] = dep[Fa] + 1 ;
     62     up[u][0] = Fa ;
     63 
     64     Insert( u , 0 , G[u] );
     65 
     66     for(int i=1 ; i <= 15 ; i++ ){
     67 
     68         up[u][i] = up[up[u][i-1]][i-1];   // 爸爸的爸爸是爷爷
     69 
     70         if( !up[u][i] )  break;         // 因为根结点为虚点0
     71 
     72         for( int j=M ; ~j ; j-- ){
     73             if( p[u][i-1][j] ) Insert( u , i , p[u][i-1][j] );
     74             if( p[up[u][i-1]][i-1][j] ) Insert( u , i ,p[up[u][i-1]][i-1][j] );
     75         }
     76     }
     77     for( register int i = head[u] ; ~i ; i=e[i].next ){
     78         if( e[i].to != Fa ) dfs( e[i].to , u ) ;
     79     }
     80 }
     81 ll query ( int u , int v ){
     82     memset( Ans , 0 , sizeof Ans );     //对于多次询问,清空线性基
     83 
     84     if( dep[u] < dep[v] ) swap(u, v);   //默认u为更低点
     85 
     86     for(int i=15;~i;i--){               //利用二进制的想法,爬到同一高度
     87         if( dep[up[u][i]] >= dep[v] ){  //同时把对爬高的过程,对应结点的值插入线性基
     88             for(int j=M;~j;j--)
     89                 if( p[u][i][j] ) Insert( p[u][i][j] );
     90             u = up[u][i] ;
     91         }
     92     }
     93 
     94     if( u^v ){          //对于不同的位置来说,需要大家同时迈步走
     95         for(int i=15;~i;i--){
     96             if( up[u][i] != up[v][i] ){ //双方都把对应的结点位置的值,插入答案线性基
     97                 for(int j=M;~j;j--){
     98                     if( p[u][i][j] ) Insert( p[u][i][j] );
     99                     if( p[v][i][j] ) Insert( p[v][i][j] );
    100                 }
    101                 u = up[u][i] , v = up[v][i];
    102             }
    103         }
    104         Insert(G[u]), Insert(G[v]), Insert(G[up[u][0]]);
    105     }else Insert(G[u]);
    106 
    107     ll res = 0;
    108     for(int j=M ; ~j ;j-- ){
    109         res = max ( res , res^Ans[j] );
    110     }
    111     return res ;
    112 }
    113 
    114 int main(){
    115     memset( head,-1,sizeof head );
    116     read(n) , read(Q) ;
    117     for( register int i=1 ; i<=n;i++ ) read(G[i]);
    118     int u,v ;
    119     for( register int i=1 ; i^n ;i++ ) {
    120         read(u) , read(v) ;
    121         add_edge(u, v), add_edge(v, u);
    122     }
    123     dfs(1, 0);
    124 
    125     while( Q-- ){
    126         read(u), read(v) ;
    127         printf("%lld
    ",query(u,v));
    128     }
    129     return 0 ;
    130 }
    131 
    132 /*
    133  *
    134 4 2
    135 11 5 7 9
    136 1 2
    137 1 3
    138 1 4
    139 2 3
    140 1 4
    141 
    142 14
    143 11
    144  */
    View Code
  • 相关阅读:
    算法学习记录单链表
    算法学习记录排序
    算法学习记录图——最小生成树之prim算法
    算法学习记录图——应用之拓扑排序(Topological Sort)
    算法学习记录图(DFS BFS)
    算法学习记录排序——冒泡排序(Bubble Sort)
    算法学习记录图——最小路径之Floyd算法
    自用SqlHelper.cs
    WPF的DataGrid的标题加粗样式
    .NET Framework 4.0不能用sqlite的问题解决方法
  • 原文地址:https://www.cnblogs.com/Osea/p/11291948.html
Copyright © 2011-2022 走看看