1054D Changing Array 【位运算+思维】
题目:戳这里
题意:两个数n,k,满足给的n个数小于2的k次方。每个数可以进行一次操作,即把a[i]换成a[i]^(1<<k-1);求最多的连续区间数使得 区间[L,R] (1<=L<=R<=n),满足: a[L] ^ a[L+1] ^ … ^ a[R-1] ^ a[R] != 0
解题思路:
首先我们知道n个数可构成的连续区间是n*(n+1)/2个,如果一个一个找肯定会超时,需要一种能快速算出[L,R]区间异或和的方法。因为异或满足交换法则。所以a[1]^a[2]^...^a[L-1] ^ a[1]^a[2]^...^a[R]=a[L]^a[L+1]^...^a[R];也就是只要纪录前缀异或和,就可以快速算出每个区间的异或值。
设前缀异或和为s[],maxx=1<<k-1。
因为相等的值相互异或为0,所以只要s[L]==s[R],则[L,R]区间的异或和为0. 此外,假设对a[i]进行一次异或操作得a[i]'=a[i]^maxx,则s[i]'=s[i]^maxx,因为异或满足s[i]^maxx^maxx=s[i],所以对于s[]数组,每进行两次^maxx的操作,当前的前缀值s[i]就相当于没有进行操作。
这样问题就转化为,经过无数次操作后,使得s[]数组中相等的数尽量的少,就可以用贪心解决了。
用map<ll,ll>mp维护每个值出现的次数。计算前缀和s[i]值时,决策s[i]=mp[s[i-1]]>mp[s[i-1]^maxx]?s[i-1]^maxx:mp[s[i-1]];用基础的组合知识(确定L,R两端点便可以确定一个区间)就可以算出最终答案。
附ac代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn = 2e5 + 10;
5 const ll mod = 998244353;
6 ll a[maxn];
7 int main() {
8
9 ll n, k;
10 scanf("%lld %lld", &n, &k);
11 for(int i = 1; i <= n; ++i) {
12 scanf("%lld", &a[i]);
13 }
14 ll ans = ll((n + 1) * n / 2);
15 ll maxx = 1ll;
16 maxx = (maxx << k) - 1ll;
17 map<ll,ll> mp;
18 mp[0] = 1;
19 ll now = 0;
20 for(ll i = 1; i <= n; ++i) {
21 now ^= a[i];
22 now = mp[now]>mp[now ^ maxx]?now^maxx:now;
23 ans -= mp[now];//组合数Cn2
24 mp[now]++;
25 }
26 printf("%lld\n", ans);
27 return 0;
28 }
1054D Changing Array 【位运算+思维】的更多相关文章
- Codeforces Round #716 (Div. 2), problem: (B) AND 0, Sum Big位运算思维
		
& -- 位运算之一,有0则0 原题链接 Problem - 1514B - Codeforces 题目 Example input 2 2 2 100000 20 output 4 2267 ...
 - 【洛谷4424】[HNOI/AHOI2018] 寻宝游戏(位运算思维题)
		
点此看题面 大致题意: 给你\(n\)个\(m\)位二进制数.每组询问给你一个\(m\)位二进制数,要求你从\(0\)开始,依次对于这\(n\)个数进行\(and\)或\(or\)操作,问有多少种方案 ...
 - codeforces 245 D. Restoring Table(位运算+思维)
		
题目链接:http://codeforces.com/contest/245/problem/D 题意:给出一个矩阵b,b[i][j]=a[i]&a[j],b[i][i]=-1.然后求a[i] ...
 - luogu 4366 [Code+#4]最短路 Dijkstra + 位运算 + 思维
		
这个题思路十分巧妙,感觉很多题都有类似的套路. 我们发现异或操作其实就是将一个数的二进制的若干个 $0$ 变成 $1$,或者一些 $1$ 变成 $0$. 而每次按照某种顺序一位一位地异或也可以起到同时 ...
 - Codeforces 1054D Changing Array 贪心+异或和
		
题意 给一个长度为\(n\)的位数为\(k\)的整数数列\(a\),一次操作可将任意\(a_i\)取反,问经过任意次操作后最多有多少个区间异或和不为\(0\) 分析 求出前缀异或和,区间异或和为\(0 ...
 - ZOJ 3870:Team Formation(位运算&思维)
		
Team Formation Time Limit: 2 Seconds Memory Limit: 131072 KB For an upcoming programming contest, Ed ...
 - Codeforces Round #672 (Div. 2) B. Rock and Lever题解(思维+位运算)
		
题目链接 题目大意 给你一个长为n(n<=1e5)的数组,让你求有多少对a[i]和a[j] (i!=j)满足a[i]&a[j]>a[i]^a[j] 题目思路 这些有关位运算的题目肯 ...
 - Divide by Zero 2021 and Codeforces Round #714 (Div. 2) B. AND Sequences思维,位运算 难度1400
		
题目链接: Problem - B - Codeforces 题目 Example input 4 3 1 1 1 5 1 2 3 4 5 5 0 2 0 3 0 4 1 3 5 1 output 6 ...
 - [题解]Mail.Ru Cup 2018 Round 1 - D. Changing Array
		
[题目] D. Changing Array [描述] 给n个整数a[1],...,a[n],满足0<=a[i]<=2^k-1.Vanya可以对这n个数中任一多个数进行操作,即将x变为x' ...
 
随机推荐
- 为什么不建议用var
			
看了这个例子估计你就会明白了 var a = 'global'; function test() { if (!a) { var a = 'part'; } console.log(a); } tes ...
 - WCNSS_qcom_cfg.ini WIFI配置文件参数详细解析
			
STA相关的一般配置 参数 含义 最小值 最大值 默认值 gNeighborLookupThreshold 1 触发roam scan发生的条件在WCNSS_qcom_cfg.ini文件中gNeigh ...
 - 探索微软开源Python自动化神器Playwright
			
相信玩过爬虫的朋友都知道selenium,一个自动化测试的神器工具.写个Python自动化脚本解放双手基本上是常规的操作了,爬虫爬不了的,就用自动化测试凑一凑. 虽然selenium有完备的文档,但也 ...
 - Failed to start ssh.service: Unit not found.
			
Failed to start ssh.service: Unit not found. 报错内容: [Centos7@localhost ~]$ service ssh start Redirect ...
 - 在ubuntu编写helloworld
			
安装vim 打开终端 输入sudo apt-get install vim-gtk 输入登陆密码 等待安装完成 编译C 创建.c文件:vim helloworld.c 编写代码,保存并退出 编译:gc ...
 - luoguP4999 烦人的数学作业
			
写在前面 这两天信息量有点大,需要好好消化一下,呼呼 \(f[i][j]\) 的转移式还是好理解的,但是对于其实际意义课上有点糊 求 \(ans_{1, x}\) 是感觉手动把数拆开看会好理解一点?? ...
 - 20200927gryz校赛心得
			
今天gyh学长给我们办了一场校内模拟赛,特地跑来记录一下心得 昨天晚上问了一下lkp学长,听说题目不卡常,不毒瘤,因此我在考试前20分钟仍在若无其事的练习着刚学的强连通分量,丝毫不慌 结果虽然rank ...
 - CF1209A
			
所谓染色,并使同颜色数都能被当前颜色中最小的数整除 也就是说,把能被某个数整除的所有数放在一起为一组,问共有几组 开始我想写个并查集但是很懒,看数据范围小的可怜,那我们写个暴力看看 因为每组的共因数都 ...
 - 最简单直接地理解Java软件设计原则之接口隔离原则
			
理论性知识 定义 接口隔离原则, Interface Segregation Principle,(ISP). 一个类对应一个类的依赖应该建立在最小的接口上: 建立单一接口,不要建立庞大臃肿的接口: ...
 - python  join()方法的使用,可以应用到tcp压测发送指定数据长度的应用
			
Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串.其中,序列中的元素应是字符串类型. 学习join()方法主要是为了配合随机数的使用,生产某个指定位数的随机数,在t ...