题目大意:
给出一个长度为n的数组A,让你求出lowbit(A[i]^A[j])的和对998244353取模的结果,其中i和j都属于[1,n]。lowbit(x)表示的是满足x xor 2^k > 0最小的2^k
解题思路:
因为数据规模很明显是5e4这样的规模,直接暴力搞必然超时,那么我们可以考虑一个问题,对于异或,如果x xor 2^k > 0的话,k一定是x二进制表示中最小的一位为1的数。
知道了这个还是无法求出来这个问题。因为涉及到异或问题,所以我们很容易想到字典树,字典树第h层的左子树表示数据自右向左第h位为0的,右子树表示第h位为1。
而这两个如果同时存在,那么这两个节点当前能表示的数的个数的乘积乘以1 << h就是这两个节点能表示的数的lowbit值。
最后答案乘以2即可。
代码:
#include <cstring> #include <iostream> using namespace std; typedef struct node { int val; int nxt[2]; }Trie; const int maxn = 50005; const int mod = 998244353; int tot; Trie t[maxn * 30]; void Insert(int x) { int tmp, p = 0; for (int i = 0; i < 30; ++i) { if (x & (1 << i)) tmp = 1; else tmp = 0; if (!t[p].nxt[tmp]) { t[tot].val = t[tot].nxt[0] = t[tot].nxt[1] = 0; t[p].nxt[tmp] = tot++; } p = t[p].nxt[tmp]; ++t[p].val; } } int query(int p, int h) { int lef = t[p].nxt[0]; int rig = t[p].nxt[1]; long long tmp = (((long long)t[lef].val * (long long)t[rig].val) % mod * (1 << h)) % mod; if (lef) tmp = (tmp + query(lef, h + 1)) % mod; if (rig) tmp = (tmp + query(rig, h + 1)) % mod; return tmp; } int main() { ios::sync_with_stdio(false); cin.tie(0); int n, x, T; cin >> T; for (int cas = 1; cas <= T; ++cas) { cin >> n; tot = 1; t[0].val = t[0].nxt[0] = t[0].nxt[1] = 0; for (int i = 0; i < n; ++i) { cin >> x; Insert(x); } long long ans = query(0, 0); ans = (2 * ans) % mod; cout << "Case #" << cas << ": " << ans << endl; } return 0; }