CF1101G (Zero XOR Subset)-less

\(\color{#0066ff}{ 题目描述 }\)

给出一个序列\(\{a_i\}\),试将其划分为尽可能多的非空子段,满足每一个元素出现且仅出现在其中一个子段中,且在这些子段中任取若干子段,它们包含的所有数的异或和不能为\(0\)

\(\color{#0066ff}{输入格式}\)

第一行一个整数\(n(1 \leq n \leq 10^5)\)表示序列长度

接下来一行\(n\)个整数\(a_i(0 \leq a_i \leq 10^9)\)描述这个序列

\(\color{#0066ff}{输出格式}\)

一行,如果不存在方案输出-1,否则输出所有合法的划分方案中最大的划分数

\(\color{#0066ff}{输入样例}\)

4
5 5 7 2

    
3
1 2 3

    
3
3 1 10

\(\color{#0066ff}{输出样例}\)

2
 
    
-1
   
    
3

\(\color{#0066ff}{数据范围与提示}\)

none

\(\color{#0066ff}{ 题解 }\)

求一下前缀异或和
把所有前缀插入线性基
答案就是线性基张成空间大小
#include<bits/stdc++.h>
#define LL long long
#define ing long long
LL in() {
    char ch; LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    return x * f;
}
const int maxn = 4e5 + 10;
int b[255], a[maxn];
void ins(int x) {
    for(int i = 40; i >= 0; i--) {
        if(x & (1LL << i)) {
            if(!b[i]) {
                b[i] = x;
                break;
            }
            x ^= b[i];
        }
    }
}

signed main() {
    int n = in();
    for(int i = 1; i <= n; i++) a[i] = a[i - 1] ^ in();
    if(a[n] == 0) printf("-1");
    else {
        for(int i = 1; i <= n; i++) ins(a[i]);
        int ans = 0;
        for(int i = 0; i <= 40; i++) if(b[i]) ans++;
        printf("%d\n", ans);
    }
    return 0;
}

转载于:https://www.cnblogs.com/olinr/p/10290391.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值