NOIP2023模拟7联测28 B. 异或

文章讲述了如何解决NOIP2023模拟测试中的问题,通过计算数组的差分并构造连通块图来确定将数组变为全零所需的最小操作次数,关键在于找到最多可以划分成异或和为0的连通块数量。
摘要由CSDN通过智能技术生成

NOIP2023模拟7联测28 B. 异或

题目大意

给定一长度为 n n n 的由非负整数组成的数组 a a a ,你需要进行一系列操作,每次操作选择一个区间 [ l , r ] [l , r] [l,r],将 a i , i ∈ [ l , r ] a_i ,i\in[l , r] ai,i[l,r] 异或上 w w w 。你需要将 a a a 全部变为 0 0 0

求最小操作次数。

思路

先搞个差分, d i = a i ⊕ a i − 1 d_i = a_i \oplus a_{i - 1} di=aiai1

我们可以发现把前 i i i d d d 异或起来就等于 a i a_i ai

那么我们就可以把区间异或操作变成一种类似于差分的双点修改操作:如果想把区间 [ l , r ] [l , r] [l,r] 异或 w w w 那么就等价于 d l ⊕ w , d r + 1 ⊕ w d_l \oplus w , d_{r + 1} \oplus w dlw,dr+1w

我们可以把 n n n 个数抽象为 n n n 个点,将修改操作抽象为两个点之间连无向边,这样的一组操作方案就是可以把整个序列分成若干个连通块的图。

那么每个连通块的操作次数就是边数。

一个大小为 x x x 的连通块的的边数为 x x x x − 1 x - 1 x1 ,只有当序列中所有 d d d 的异或和为 0 0 0 时边数才为 x − 1 x - 1 x1 ,否则都是 x x x

所以一个子序列 s s s 的答案就是把 s s s 的大小减去 s s s 划成最多的异或和为 0 0 0 的数量。

f s f_s fs 为能够把 s s s 划分成最多的异或和为 0 0 0 的数量
f s = max ⁡ f t + f s ⊕ t , ( s & t = 0 ) f_s = \max f_t + f_{s \oplus t} , (s \& t = 0) fs=maxft+fst,(s&t=0)

code

#include <bits/stdc++.h>
#define fu(x , y , z) for(int x = y ; x <= z ; x ++)
#define LL long long
using namespace std;
int n , f[1 << 18] , g[1 << 18];  
LL a[25] , d[25] , sum;
int main () {
    freopen ("xor.in" , "r" , stdin);
    freopen ("xor.out" , "w" , stdout);
    scanf ("%d" , &n);
    fu (i , 1 , n) scanf ("%lld" , &a[i]);
    fu (i , 1 , n) d[i] = a[i] ^ a[i - 1];
    fu (i , 1 , (1 << n) - 1) {
        sum = 0;
        fu (j , 1 , n) {
            if (i & (1 << j - 1)) {
                sum ^= d[j];
            }
        }
        if (!sum) f[i] = 1;
    }
    fu (s , 1 , (1 << n) - 1) {
        g[s] = f[s];
        for (int t = (s - 1) & s ; t ; t = (t - 1) & s) {
            if (f[t])
                g[s] = max (g[s] , g[s ^ t] + 1);
        }
    }
    printf ("%d" , n - g[(1 << n) - 1]);
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值