C ++ | 蓝桥题库—异或森林(双指针)

文章介绍了如何使用双指针算法解决一个关于判断数组元素异或和的前缀是否为完全平方数的问题,通过异或操作和计数非完全平方数来计算满足条件的数组数量。
摘要由CSDN通过智能技术生成
双指针
  •  基础算法中概括的双指针首先不是指针,是用两个数来代替坐标进行增加或减少的操作,从而达到确定区间的作用。
  • 双指针的使用前提是,有一个区间 [l, r] 满足条件,并且他的任意一个子数组都满足条件。

题解:因数个数为偶数 <=>(等价于) 非完全平方数 

我遇到的问题是完全平方数sq的取值应该是j * j,列举的是前200个完全平方数,因为非平方数明显比平方数要多,采用正难则反的原则。如果是与平方数异或为0的那么证明是枚举到这个平方数了,拿总数减去这个当前平方数。

#include <bits/stdc++.h>
const int N = 1e5 + 9;
using namespace std;
int a[N], pre[N], cnt[N];

int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		pre[i] = pre[i - 1] ^ a[i]; //数组的异或和前缀
	cnt[0] = 1;
	//总数ans减去不满足的数量就是答案
	int ans = n * (n + 1) / 2; //
	for (int i = 1; i <= n; i++) {
		for (int j = 0; j <= 200; j++) { //从0开始:0的因数个数也是奇数个。
			int sq = j * j;
			ans -= cnt[pre[i] ^ sq]; //如果pre[i]和sq异或的结果为0,就是相等,那么pre[i]是平方和,那么减去1。
			//因为上面让cnt[0]=1了。
		}
		cnt[pre[i]]++;//至于这段代码,若pre[i]^sq = pre[j]等价于pre[i]^pre[j] = sq,说明原数组的i-j的元素异或和是平方和。
		//因为我们相当于对数组只进行一重循环,所以每遍历完一个前缀异或和都要放到cnt数组里面,cnt数组的作用就是是否减1。
		//这个操作就相当于二重循环,非常经典
	}
	cout << ans;
	return 0;
}
思维拓展
  • 异或是一个很强大的功能,| a - b | <= a ^ b <= a + b,在任何条件下是成立的;
  • 在a ^ b ^ c = a + b + c成立的前提下,a ^ b = a + b; b ^ c = b + c;
  • a + b >= a | b >= max(a,b);
  • 0 <= a & b <= min(a, b);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值