关于此题Codeforces Round 984_F. XORificator 3000 异或前缀和
记录一个trick:
\(\bigoplus_{i=1}^{n} = \left\{\begin{matrix}n, n mod 4 = 0
\\1, n mod 4 = 1
\\n+1, n mod 4 = 2
\\0, n mod 4 = 3
\end{matrix}\right.\)
那这道题就不难了。所有的数被分为两部分,第一部分是二进制下第\(i\)位及以上的部分,第二部分则是剩下的部分。根据题意要求第二部分为\(k\),那么我们只需要计算出\([l-1,r]\)区间内有多少个第二部分是\(k\)的数,如果是奇数就让\(ans\)异或上\(k\)。接着算第一部分,我们可以先忽略掉第二部分,即让\(l-1\)和\(r\)都右移\(i\)位,此时我们再计算\([l-1,r]\)的异或前缀和后再左移i位回去,得到的就是第一部分的值,再让\(ans\)异或上这一部分的值即可。
#include<bits/stdc++.h>
using namespace std;
long long t;
long long l,r,i,k;
long long getnum(long long x) {
if(x % 4 == 0) return x;
if(x % 4 == 1) return 1;
if(x % 4 == 2) return x + 1;
if(x % 4 == 3) return 0;
}
long long work(long long m,long long x,long long pos) {
if((1ll << pos) <= x) return 0;
long long res = 0;
long long tmp = m >> pos;
if((tmp << pos) + x <= m) return tmp + 1;
else return tmp;
}
void solve() {
cin >> l >> r >> i >> k;
l--;
long long ans = getnum(r) ^ getnum(l);
long long num = work(r,k,i) - work(l,k,i);
if(num & 1) ans ^= k;
long long tr = (r >> i);
if((tr << i) + k > r) tr--,tr = max(tr,0ll);
long long tl = (l >> i);
if((tl << i) + k > l) tl--,tl = max(tl,0ll);
long long tmp = getnum(tr) ^ getnum(tl);
tmp <<= i;
ans ^= tmp;
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--) solve();
return 0;
}

浙公网安备 33010602011771号