【题解】ARC133D - Range XOR

我们先求个前缀和 \(s_i = \bigoplus\limits_{x = 1}^ix\),问题转化为求满足 \(L - 1 \le l < r \le R\) 且 \(s_r \oplus s_l = V\) 的二元组 \((l,r)\) 个数。

对于 \(s_i\),不难发现以 \(4\) 为循环有固定的规律:\(s_{4x} = 4x,s_{4x+1} = 1, s_{4x+2} = 4x+3, s_{4x+3} = 0\)。

所以我们可以将 \(V / 4\) 和 \(V\bmod 4\) 分开计算,枚举 \(l \bmod 4\) 和 \(r \bmod 4\),然后计算有多少 \(l/4\) 和 \(r/4\) 的异或和为 \(V/4\),直接暴力记搜即可。

int c[4] = {0, 1, 3, 0};
struct node{
	int x, y, v;
	bool operator<(const node o)const{
		if(x != o.x)return x < o.x;
		if(y != o.y)return y < o.y;
		return v < o.v;
	}
};
map<node,int>h;
int calc(int l,int r,int v){
	if(!v)return (min(l, r) + 1) % P;
	if(!l && !r)return 0;
	node cur{l, r, v};
	if(h.count(cur))return h[cur];
	int sum = 0;
	rep(x, 0, 1){
		int y = (v ^ x) & 1;
		if(x > l || y > r)continue;
		ad(sum, calc((l - x) / 2, (r - y) / 2, v / 2));
	}
	return h[cur] = sum;
}
int ask(int l,int r,int v){
	if(l < 0)return 0;
	int ans = 0;
	rep(i, 0, 3)rep(j, 0, 3){
		int w = v ^ c[i] ^ c[j];
		if(i > l || j > r)continue;
		int p = (l - i) / 4, q = (r - j) / 4;
		if(w % 4)continue;
		if(i & 1){
			if(j & 1){
				if(!w)ad(ans, ((p + 1) % P) * ((q + 1) % P) % P);
			}
			else{
				if(w / 4 <= q)ad(ans, (p + 1) % P);
			}
		}
		else{
			if(j & 1){
				if(w / 4 <= p)ad(ans, (q + 1) % P);
			}
			else{
				h.clear();
				ad(ans, calc(p, q, w / 4));
			}
		}
	}
	if(!v)su(ans, min(l, r) + 1);
	return ans;
}
int l, r, v;
signed main() {
	read(l), read(r), read(v), l --;
	int ans = ((ask(r, r, v) - 2 * ask(l - 1, r, v) + ask(l - 1, l - 1, v)) % P + P) % P;
	cout << ans * ((P + 1) / 2) % P << endl;
	return 0;
}
上一篇:一场 NOIP 模拟赛


下一篇:古代猪文--(全是数论QwQ)