codeforces 1041 E.Vasya and Good Sequences(暴力?)

E. Vasya and Good Sequences

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

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.

Input

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$$$.

Output

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.

Examples

Input

36 7 14

Output

2

Input

41 2 1 16

Output

4

Note

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.

题意

对于任何一个$$$a_i$$$,可以将其表示为$$$2$$$进制并任意更改它里面1的位置。对于区间[l,r],如果对其中一些数执行任意次这样的操作,从而使得区间的异或和为0,就称这段区间是good。给$$$n$$$个数,$$$1\le a_i\le 10^{18}$$$,求有多少个子区间是good。

分析

异或和只与二进制中$$$1$$$的个数有关,所以用$$$b_i$$$记录$$$(a_i)_2$$$中的$$$1$$$的个数,形成一个新的数组$$$b[n]$$$,之后就不再考虑数组$$$a[n]$$$了。
为了方便叙述,用$$$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 = 0;
    while (x)res += x & 1, x >>=1;
    return res;
}
int b[300005]={0},fre[300005];
LL ai;
int cnt0 = 0, cnt1 = 0;
int main(){
    int n;
    scanf("%d", &n);
    for(int i=1;i<=n;++i)    {
        scanf("%I64d", &ai); b[i] = cnt(ai); fre[i] = fre[i - 1] + b[i];
        if (fre[i] & 1)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 - 1) / 2+1LL*cnt0*(cnt0+1)/2;

    //遍历所有以i为起点的区间
    for(int i=1;i<=n;++i)    {
        int maxn = 0,sum;
        //只检查到长度为64
        for(int j=0;j<=64&&i+j<=n;++j){
            if (maxn < b[i + j])maxn = b[i + j];
            sum = fre[i + j] - fre[i - 1];
            if ((sum & 1) == 0 && (maxn<<1) > sum)ans--;
        }
    }
    printf("%I64d", ans);
}

原文地址:https://www.cnblogs.com/tobyw/p/9714952.html

时间: 2024-10-30 18:40:04

codeforces 1041 E.Vasya and Good Sequences(暴力?)的相关文章

Codeforces 1053 B - Vasya and Good Sequences

B - Vasya and Good Sequences 思路: 满足异或值为0的区间,必须满足一下条件: 1.区间中二进制1的个数和为偶数个; 2.区间二进制1的个数最大值的两倍不超过区间和. 如果区间长度大于128,第二个条件肯定满足,所以我们只要暴力区间长度小于128的就可以了 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using

Codeforces 6D Lizards and Basements 2 dfs+暴力

题目链接:点击打开链接 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h> #include<queue> #include<string> #include<stdlib.h> #include<a

Codeforces 451C Predict Outcome of the Game(暴力)

题目连接:Codeforces 451C Predict Outcome of the Game 题目大意:题意有点坑,就是三支球队有n场比赛,错过了k场,即这k场比赛不知道输赢,只知道第一支球队和第二支球队胜局情况差d1,第二和第三差d2,问说最后有没有可能三支队伍胜局数相同. 解题思路:考虑四种情况下的场数u,是否为3的倍数,u/3后是否比当前情况下胜局数最高的队伍大,并且还要判断该情况是否可行. #include <cstdio> #include <cstring> #in

[CF1030E]Vasya and Good Sequences

[CF1030E]Vasya and Good Sequences 题目大意: 给定一个长度为\(n(n\le3\times10^5)\)的数列\(a_i(1\le a_i\le10^{18})\).可以任意对若干数进行操作,交换这个数的任意二进制位.求有多少区间,使得这个区间内的数经过操作使得异或和为\(0\). 思路: 显然这与\(a_i\)本身的值无关,只与二进制下\(1\)的个数有关. 一个区间\([l,r]\)需要满足以下条件: 二进制下\(1\)的个数为偶数: 二进制下\(1\)的个

Codeforces #550 (Div3) - G.Two Merged Sequences(dp / 贪心)

Problem  Codeforces #550 (Div3) - G.Two Merged Sequences Time Limit: 2000 mSec Problem Description Two integer sequences existed initially, one of them was strictly increasing, and another one — strictly decreasing. Strictly increasing sequence is a

[Codeforces 1058E] Vasya and Good Sequences

[题目链接] https://codeforces.com/contest/1058/problem/E [算法] 显然 , 我们只需考虑序列中每个数的二进制表示下1的个数即可. 不妨令Ai表示第i个数的二进制表示下1的个数. 一个子序列[L,R]是"好"的当且仅当 : 1. sigma{ Ai }  (L <= i <= R) 为偶数 2. max{ Ai } (L <= i <= R) <= sigma{ Ai } / 2 枚举序列左端点L , 可以用

Codeforces 778A:String Game(二分暴力)

http://codeforces.com/problemset/problem/778/A 题意:给出字符串s和字符串p,还有n个位置,每一个位置代表删除s串中的第i个字符,问最多可以删除多少个字符使得s串依旧包含p串. 思路:想到二分,以为二分做法依旧很暴力.但是别人的做法确实就是二分暴力搞啊. 枚举删除字符数,然后判断的时候如果s串包含p串,那么可以往右区间找,否则左区间找. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #def

Codeforces Gym 100286J Javanese Cryptoanalysis 傻逼暴力

原题地址:http://codeforces.com/gym/100286/attachments/download/2013/20082009-acmicpc-northeastern-european-regional-contest-neerc-08-en.pdf 此题题意是给你一个单对单密文,让你还原为原文,原文有个性质是,每个单词都是元音和辅音交替组成. 做法是直接5重for,暴力枚举AEIOU分别对应的字母,然后检查,然后输出 详见代码: //#include<iostream>

codeforces 1041 E. Tree Reconstruction 和度数有关的构造树

CF 1041E:http://codeforces.com/contest/1041/problem/E 题意: 告诉你一个树的节点个数,显然有n-1条边.已知去掉一条边后,两个集合中最大的节点值.问原来的树形状是怎么样的,构造不出来就输出NO. 思路: 这里说的“度数”可能有点不恰当.指以这个点引出一条链的长度,链上点的值小于这个点. 我想着这应该是可以作为一条链的,但是一直没有想到向节点度数上去想.首先,输入的一对值中,有一个一定是等于n的,那另一个值我们给它度数++.我们把度数为0的点从