内容:
从0往后异或,我们发现,每四个都有规律
相当于对于数i,根据i%4可以直接推出0到i的前缀和
例题:XORificator 3000
大意:
求[L, R]区间不与k同余的数的异或和
思路:
直接求比较难求,可以转化一下,不与k同余的数的异或和等于与k同余的数的异或和再异或一下[L,R]区间内所有数的异或和
可以容易求得[L,R]区间内异或和 = f[R] ^ f[L - 1]
与k同余的数,他们低i位都是k,高位依次加一,可以分别考虑:对于高位,直接求出高位区间然后异或求异或和即可,对于低位,如果同余数为偶数就为0,如果为奇数,就为k
代码:
#include <bits/stdc++.h>
#include <array>
using namespace std;
#define int long long
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
#define pb push_back
#define vi vector<int>
#define vvi vector<vector<int>>
#define vii vector<pair<int, int>>
#define ff first
#define ss second
// ++ ~! */+- <<>> <> == &^| &&|| =
int f(int x) // 前缀异或和
{
int num = x % 4;
if (num == 0)return x;
else if (num == 1)return 1;
else if (num == 2)return x + 1;
else return 0;
}
void solve()
{
int l, r, i, k;
cin >> l >> r >> i >> k;
int m = 1ll << i;
int num1 = f(r) ^ f(l - 1); //l,r 区间异或和
int a = l >> i, b = r >> i;
if (l % m > k)a ++; // a 代表与k同模的最小值的高位
if (r % m < k)b --; // b 代表与k同模的最大值的高位
int num2 = f(b) ^ f(a - 1); // l,r区间内与k同余数的高位异或和
num2 <<= i;
if ((b - a + 1) & 1)num2 += k;
int ans = num1 ^ num2;
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) solve();
return 0;
}
/* /\_/\
* (= ._.)
* / > \>
*/
参考题解
Codeforces Round 984 (Div. 3) F.XORificator 3000 题解 - Hello World