codeforces 1041 E.Vasya and Good Sequences(暴力?)
2 seconds
256 megabytes
standard input
standard output
Vasya has a sequence $$$a$$$ consisting of $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$. Vasya may pefrom the following operation: choose some number from the sequence and swap any pair of bits in its binary representation. For example, Vasya can transform number $$$6$$$ $$$(\dots 00000000110_2)$$$ into $$$3$$$ $$$(\dots 00000000011_2)$$$, $$$12$$$ $$$(\dots 000000001100_2)$$$, $$$1026$$$ $$$(\dots 10000000010_2)$$$ and many others. Vasya can use this operation any (possibly zero) number of times on any number from the sequence.
Vasya names a sequence as good one, if, using operation mentioned above, he can obtain the sequence with bitwise exclusive or of all elements equal to $$$0$$$.
For the given sequence $$$a_1, a_2, \ldots, a_n$$$ Vasya'd like to calculate number of integer pairs $$$(l, r)$$$ such that $$$1 \le l \le r \le n$$$ and sequence $$$a_l, a_{l + 1}, \dots, a_r$$$ is good.
The first line contains a single integer $$$n$$$ ($$$1 \le n \le 3 \cdot 10^5$$$) — length of the sequence.
The second line contains $$$n$$$ integers $$$a_1, a_2, \dots, a_n$$$ ($$$1 \le a_i \le 10^{18}$$$) — the sequence $$$a$$$.
Print one integer — the number of pairs $$$(l, r)$$$ such that $$$1 \le l \le r \le n$$$ and the sequence $$$a_l, a_{l + 1}, \dots, a_r$$$ is good.
3
6 7 14
2
4
1 2 1 16
4
In the first example pairs $$$(2, 3)$$$ and $$$(1, 3)$$$ are valid. Pair $$$(2, 3)$$$ is valid since $$$a_2 = 7 \rightarrow 11$$$, $$$a_3 = 14 \rightarrow 11$$$ and $$$11 \oplus 11 = 0$$$, where $$$\oplus$$$ — bitwise exclusive or. Pair $$$(1, 3)$$$ is valid since $$$a_1 = 6 \rightarrow 3$$$, $$$a_2 = 7 \rightarrow 13$$$, $$$a_3 = 14 \rightarrow 14$$$ and $$$3 \oplus 13 \oplus 14 = 0$$$.
In the second example pairs $$$(1, 2)$$$, $$$(2, 3)$$$, $$$(3, 4)$$$ and $$$(1, 4)$$$ are valid.
为了方便叙述,用$$$x\oplus y$$$表示对$$$x,y$$$进行任意调整后,可能的异或值的集合。容易发现两个数的情况($$$x\lt y$$$),结果是一个公差为2的等差序列:
$$$$$$
\begin{align}
x\oplus y=\{|y-x|,\ |y-x|+2,\ ...,\ x+y \}
\end{align}
$$$$$$
三个数的情况($$$x\lt y\lt z$$$),结果也是公差为2的等差序列:
$$$$$$
\begin{align}
x\oplus y\oplus z=\{min\{|z-t|,\ t\in x\oplus y\},\ ...,\ x+y+z \}
\end{align}
$$$$$$
分析可以发现,区间可能的异或值的范围,上限是区间和,下限是一个小于最大元素的数,要判断异或值能否为0,最暴力的方法,就是把$$$min\{...\}$$$里面遍历一遍,看0是不是在其中,而这需要很大的代价。
有一个更好的解决办法,注意到上限是一个很容易维护的值,而下限一定小于区间的最大元素,假设$$$[l,r]$$$内最大和第二大的数分别为$$$b_i,\ b_j$$$,把$$$b_i$$$单独拿出来,剩下的数形成新的区间,那么新区间的上限就是的新的区间和,下限就是一个小于$$$b_j$$$的数,所以下限一定小于$$$b_i$$$。要让原区间下限为0,就转而去判断新区间对应的等差序列中有没有$$$b_i$$$,因为如果有,就可以抵消掉,从而原区间的下限就是0。具体的来说,$$$b_i$$$要在其中,要满足两个条件:
【1】上限大于或等于$$$b_i$$$;
【2】$$$b_i$$$与上限同奇偶;
这样一来,通过上限就能确定区间是否为good,完全避免了对下限的考虑了。但是单独把$$$b_i$$$提出来还是很麻烦,不如把条件转化为对整个区间的限制:
【1】区间和大于或等于最大元素的两倍;
【2】区间和是偶数;
还有一个性质,$$$b_i$$$的范围是1~63,也就意味着,只要区间的长度不小于64,区间和≥63+$$$b_i$$$≥$$$2b_i$$$,就一定满足条件【1】,所以只用考虑所有长度小于64的区间,于是问题的规模就缩小到了64n,就变成了一个使劲码就能做出来的题了。
一种比较好的写法是,先算求和为偶数的区间的总个数,再遍历所有长度小于64且和为偶数的区间,从总个数中去掉不满足条件的,剩下的个数就是答案。
#include<stdio.h>
typedef long long LL;
int cnt(LL x) {
int res = ;
while (x)res += x & , x >>=;
return res;
}
int b[]={},fre[];
LL ai;
int cnt0 = , cnt1 = ;
int main(){
int n;
scanf("%d", &n);
for(int i=;i<=n;++i) {
scanf("%I64d", &ai); b[i] = cnt(ai); fre[i] = fre[i - ] + b[i];
if (fre[i] & )cnt1++;
else cnt0++;
}
/*求和为偶数的区间个数:
*
*对于前缀和为奇数的[0,l1], [0,l2], ..., [0,lcnt1]
* 对l1而言,它和后面的组合起来,[l1+1,l2], [l1+1,l3], ..., [l1+1,lcnt1]的和一定全都是偶数
* l2~lcnt1也同理,共cnt1-1+cnt1-2+...1=cnt1(cnt1-1)/2个
*
* 对于和为偶数的区间[0,r1], [0, r2], ..., [0,rcnt0]
*
* 不仅和奇数的相同,每个区间本身也要加入计数
* 所以共cnt0+cnt0-1+...+1=(cnt0+1)cnt0/2个
*/
LL ans = 1LL * cnt1*(cnt1 - ) / +1LL*cnt0*(cnt0+)/; //遍历所有以i为起点的区间
for(int i=;i<=n;++i) {
int maxn = ,sum;
//只检查到长度为64
for(int j=;j<=&&i+j<=n;++j){
if (maxn < b[i + j])maxn = b[i + j];
sum = fre[i + j] - fre[i - ];
if ((sum & ) == && (maxn<<) > sum)ans--;
}
}
printf("%I64d", ans);
}
codeforces 1041 E.Vasya and Good Sequences(暴力?)的更多相关文章
- Codeforces 1053 B - Vasya and Good Sequences
B - Vasya and Good Sequences 思路: 满足异或值为0的区间,必须满足一下条件: 1.区间中二进制1的个数和为偶数个; 2.区间二进制1的个数最大值的两倍不超过区间和. 如果 ...
- Codeforces #550 (Div3) - G.Two Merged Sequences(dp / 贪心)
Problem Codeforces #550 (Div3) - G.Two Merged Sequences Time Limit: 2000 mSec Problem Description T ...
- [CF1030E]Vasya and Good Sequences
[CF1030E]Vasya and Good Sequences 题目大意: 给定一个长度为\(n(n\le3\times10^5)\)的数列\(a_i(1\le a_i\le10^{18})\). ...
- codeforces 1041 e 构造
Codeforces 1041 E 构造题. 给出一种操作,对于一棵树,去掉它的一条边.那么这颗树被分成两个部分,两个部分的分别的最大值就是这次操作的答案. 现在给出一棵树所有操作的结果,问能不能构造 ...
- [Codeforces 1053B] Vasya and Good Sequences
Link: Codeforces 1053B 传送门 Solution: 其实就是暴力 观察需要满足的条件: 1.个数和为偶数 2.最大个数不大于其它所有个数的和 如果只有第一个条件记录前缀和的奇偶性 ...
- Codeforces Round #512 (Div. 2, based on Technocup 2019 Elimination Round 1) E. Vasya and Good Sequences(DP)
题目链接:http://codeforces.com/contest/1058/problem/E 题意:给出 n 个数,对于一个选定的区间,区间内的数可以通过重新排列二进制数的位置得到一个新的数,问 ...
- Codeforces Round #262 (Div. 2) A. Vasya and Socks【暴力/模拟/袜子在可以在合法情况下增加后用几天】
A. Vasya and Socks time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- [Codeforces 1058E] Vasya and Good Sequences
[题目链接] https://codeforces.com/contest/1058/problem/E [算法] 显然 , 我们只需考虑序列中每个数的二进制表示下1的个数即可. 不妨令Ai表示第i个 ...
- Codeforces Round #512 E - Vasya and Good Sequences
有时候觉得自己就是个思路搬运机,只会搬运思路 这个题首先说了求的是好区间的个数, 好区间满足条件: 1.二进制位1的数量和为偶数 2.w[i]表示a[i]的二进制上1的个数 ,sum[i] = ...
随机推荐
- 菜鸟vimer成长记——第0章、我眼中的vim学习
这是一系统总结vim的学习文章,记录我自己学习vim的过程和感悟.与此同时也想分享出来给大家,欢迎大家互相讨论和学习. 在这里假设你们对vim已经有了一些基本的认识或者说已经使用过几个月的vim.该系 ...
- c# url链接转成二维码图片,再转成byte[]二进制流,输出到前段ajax
需要用到的 dll 添加引用 代码: //获取配置文件设置的url string urllink = ConfigurationManager.AppSettings["urllink&qu ...
- [C++]linux下实现rm()函数删除文件或目录
转载请注明原创:http://www.cnblogs.com/StartoverX/p/4600866.html 在linux下有两个函数可以用来删除文件: #include <unistd.h ...
- Laya资源加载小记
Laya.Loader负责资源的加载逻辑,被LoaderManager管理. Laya支持多种类型资源加载,也支持自定义类型加载.不同类型的加载方式可能不同. Laya.Loader缓存已经被加载过得 ...
- dom学习要点
Dom操作 1.文本内容操作 - innerText:操作文本 - innerHtml:操作全内容 //innerText标签: <div id='i2' ><a>土味程序员& ...
- java按照字节切割字符串,解决汉字的问题
编写一个截取字符串的函数,输入为一个字符串,截取开始地址,截取字节数,输出为按字节截取的字符串. 但是要保证汉字不被截半个, 如“我ABC”,0,4,应该截为“我AB”,输入“我ABC汉DEF”,1, ...
- 阿里云解析记录应对家里动态IP
<?php #需要配置的项 define('ACCESSKEYID',''); #阿里云用户密钥ID 获取方法 https://help.aliyun.com/knowledge_detail/ ...
- 编译Android VNC Server
1,在如下地址checkout源代码,我checkout的版本为0.9.7http://code.google.com/p/android-vnc-server/source/checkout 2,在 ...
- Python更新库
查看系统里过期的python库,可以用pip命令 [root@vnode33 sim-enb-sgi]# pip list #列出所有安装的库 Package Version ------------ ...
- sprint2(第四天)
由于最近网络不行,更新的代码push不上Github,组员之间又不能clone得到最新的项目,所以这几天都没有更新到Github 燃尽图