ABC295D 题解

萌萌思维题,但是考场差一点AC。


题目等价于寻找区间 \([l,r]\) 满足数字 \(0\)~\(9\) 各出现偶数次。

根据
找筷子
这道题的经验,出现偶数次 = 异或和为 \(0\)

但是发现如果和找筷子一样直接异或到一起会出现冲突
(例子:$3 \oplus 5 \oplus 6 = 0 $)。

所以变成二进制数就可以了。


朴素想法是暴力枚举每个区间,然后异或判断。复杂度 \(O(|S|^3)\),显然无法通过本题。

利用前缀和进行优化,可以把复杂度降到 \(O(|S|^2)\),仍然不能通过本题。


由于题目要求的只是数量,不需要求出每个区间。

考虑满足条件的 \([l,r]\) 区间性质,必满足 \(xorsum_{l-1} = xorsum_{r}\)

那么求 \(xorsum\) 时记录当前值的出现次数 \(cnt_x\),以 \(r\) 为右端点,满足条件的 \(l\) 数量是 \(cnt_x - 1\),也就是区间数量。

累加即可。


code:

#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define LL long long

const int N=5e5+5;
int a[N],m[N];
int cnt;
LL ans;//不开long long见祖宗

int main()
{
	while(char c=getchar()){
		if(isdigit(c)) a[++cnt]=c-'0';
		else break;
	}
	int x=0;
	m[0]=1;//处理以1为左端点的情况
	rep(i,cnt){
		x^=(1<<a[i]);//状压
		ans+=m[x];
		m[x]++;
	}
	cout<<ans<<endl;
	return 0;
}


posted @ 2024-03-01 22:25  Cindy_Li  阅读(18)  评论(0)    收藏  举报