线性基

线性基

https://blog.csdn.net/a_forever_dream/article/details/83654397这个博客学习的

看完了博客虽然还是不能完全理解线性基,但是大概懂了是怎么用的

1.求一个序列的最大/最小异或

2.求一个序列第k小异或

下面是一些入门题:

To xor or not to xor SGU - 275

求n个数的最大异或

#include <cstdio>
long long d[70];
int main() {
    int n;
    scanf("%d", &n);
    long long a, ans = 0;
    for(int i = 0; i < n; i++) {
        scanf("%lld", &a);
        for(int j = 60; j >= 0; j--) {
            if(a & (1LL << j)) {
                if(d[j]) a ^= d[j];
                else {
                    d[j] = a;
                    break;
                }
            }
        }
    }
    for(int i = 60; i >= 0; i--) {
        if((ans ^ d[i]) > ans) ans ^= d[i];
    }
    printf("%lld\n", ans);
    return 0;
}

P4570 [BJWC2011]元素

#include <cstdio>
#include <algorithm>
using std::sort;
typedef long long LL;
struct node
{
    LL a, b;
}G[1010];
bool cmp(node x, node y) {
    return x.b > y.b;
}
LL d[110];
int main() {
    int n;
    LL ans = 0;
    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        scanf("%lld %lld", &G[i].a, &G[i].b);
    }
    sort(G, G +n, cmp);
    for(int i = 0; i < n; i++) {
        for(int j = 60; j >= 0; j--) {
            if(G[i].a & (1LL << j)) {
                if(d[j]) G[i].a ^= d[j];
                else {
                    d[j] = G[i].a;
                    ans += G[i].b;
                    break;
                }
            }
        }
    }
    printf("%lld\n", ans);
    return 0;
}

P3857 [TJOI2008]彩灯

#include <cstdio>
typedef long long LL;
LL d[110];
int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    while(m--) {
        char s[110];
        LL a = 0;
        scanf("%s", s);
        for(int i = 0; i < n; i++) {
            if(s[i] == 'O') {
                a += (1LL << (n - i - 1));
            }
        }
        //printf("aa %lld\n", a);
        for(int i = 60; i >= 0; i--) {
            if(a & (1LL << i)) {
                if(d[i]) a ^= d[i];
                else {
                    d[i] = a;
                    break;
                }
            }
        }
    }
    int cnt = 0;
    for(int i = 0; i <= 60; i++) {
        if(d[i]) cnt++;
    }
    printf("%lld\n", (1LL << cnt) % 2008);
    return 0;
}

XOR HDU - 3949

t组数据,n个数的序列,q组询问第k小的异或值。

#include <cstdio>
#include <cstring>
typedef long long LL;
LL d[70];

int main() {
    int t;
    scanf("%d", &t);
    for(int k = 1; k <= t; k++) {
        printf("Case #%d:\n", k);
        memset(d, 0, sizeof(d));
        int n;
        LL a;
        scanf("%d", &n);
        for(int i = 0; i < n; i++) {
            scanf("%lld", &a);
            for(int j = 60; j >= 0; j--) {
                if(a & (1LL << j)) {
                    if(d[j]) a ^= d[j];
                    else {
                        d[j] = a;
                        break;
                    }
                }
            }
        }
        int cnt = 0;
        for(int i = 0; i <= 60; i++) {
            if(d[i]) cnt++;
        }
        //printf("cnt %d\n", cnt);
        for(int i = 1; i <= 60; i++) {
            for(int j = 1; j <= i; j++) {
                if(d[i] & (1LL << (j - 1))) d[i] ^= d[j-1];
            }
        }
        int q;
        scanf("%d", &q);
        while(q--) {
            scanf("%lld", &a);
            if(a == 1 && cnt < n) {
                printf("0\n");
                continue;
            }
            if(cnt < n && (1LL << cnt) < a) {
                printf("-1\n");
                continue;
            }
            if(cnt == n && (1LL << cnt) <= a) {
                printf("-1\n");
                continue;
            }
            LL ans = 0;
            if(cnt < n) a--;
            for(int i = 0; i <= 60; i++) {
                if(d[i]) {
                    if(a % 2 == 1) ans ^= d[i];
                    a /= 2;
                }
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}

posted @ 2020-03-30 21:47  小饭hhh  阅读(129)  评论(0编辑  收藏  举报