关于此题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;
}
posted @ 2025-03-20 14:44  孤枕  阅读(21)  评论(0)    收藏  举报