Codeforces Round#841(Div2) - Even Subarrays
相关概念(小学数学)
完全平方数:
一个数如果是另一个整数的完全平方,那么我们称这个数是完全平方数,也叫做平方数。
性质:
- 完全平方数末尾只能是0, 1, 4, 5, 6, 9
- 奇数的平方的个位数字位奇数,十位数字位偶数
这里推导一下为什么一个数含有奇数个因子,那么其必然是完全平方数(充要条件):
充分性证明: 对于 \(x=p^{a_1}_{1}p^{a_2}_{2}...p^{a_n}_{n}\), 他的因子数可以写成\((a_1 + 1) * (a_2 + 1) * ... *(a_n + 1)\),显然若其因子数为奇数,则对于每一个\(a_i + 1\) 必定为奇数。所以\(a_i\) 为偶数,因此该数为完全平方数。
必要性证明:如果一个数为完全平方数,那么\(x=p^{a_1}_{1}p^{a_2}_{2}...p^{a_n}_{n}\), 且\(x=n^2\) , 那么对于每一个\(p^{a_i}_i\) 其都能化成成\(x_i^2\), 因此其因子数都为偶数。
思路
前缀异或数组, 异或性质
如果枚举每个,i,j显然 \(O(n^2)\)的复杂度会超时,这时我们需要用到异或的性质
\(a \oplus b = c\) , 则\(a \oplus c = b\)
假设我们已经由前缀异或数组,枚举每个区间我们的操作是\(i\le j\)
\(f[i]\oplus f[j - 1] = x^2\) (这里\(0< x < 2n\) 因为异或不会进位,所以我们左移一下,这个数一定不会超过)
由上述性质,得
\(f[i] \oplus x^2=f[j -1]\)
那么我们通过枚举\(f[i]\space, 1\le i \le n\), 再枚举x
最后复杂度\(O(n\sqrt n)\)
#include <iostream>
#include <vector>
using namespace std;
#define ll long long int
const int N = 2e5 + 10;
void solve() {
long long n, tot; cin >> n;
vector<int> a(n + 1), arr(2 * n, 0); tot = (n * (n + 1)) / 2;
int curr = 0;
arr[0] ++;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
curr ^= a[i];
for (int k = 0; k * k < 2 * n; k ++) {
if ((curr ^ (k * k)) < 2 * n) {
tot -= arr[curr ^ (k * k)];
}
}
arr[curr] ++;
}
cout << tot << "\n";
}
int main() {
ios::sync_with_stdio(false);
int _;
cin >> _;
while (_ --) {
solve();
}
}