CF Gym102331B Bitwise Xor 题解
Solution
Nanami^2 Even in the rain.
2023年09月21日
预计阅读 4 分钟
788 字
Solution
引理:一个集合中异或值最小的数对,出现在把所有元素递增排序后相邻的两个数中。
证明:反证法。假设引理不成立,设此时最小数对为 ,且存在 满足 。考虑极大的二进制位 ,满足 的第 位上是 , 的第 位上是 ,从而 的第 位是 。
- 如果 的第 位是 ,那么 的第 位是 ,从而 。
- 如果 的第 位是 ,那么一定存在极大的二进制位 ,满足 的这一位是 , 的这一位是 。然后用类似的方法讨论也能得到 。
所以我们把所有数递增排序。
设 为以 结尾的方案数,显然有转移
考虑用 0-1 Trie 优化这个 DP。
把 挂到 Trie 的叶子上,然后在 Trie 树上跑两步。
这种情况比较 ,并且它的处理方法和 只能说毫不相关。所以先把这种情况单独拎出来,反正就是一个叶子的贡献。
什么时候能直接贡献一棵子树的所有叶子呢? 的当前位为 时,直接累加与 当前位相反的那一棵子树就行,此时一定满足 。
然后我们就要使得 在已经处理的数位上等于 ,所以如果 与 在当前位相同,我们就往 儿子处找,否则就往 儿子处找。
// Problem: B. Bitwise Xor// Contest: Codeforces - 2019 Summer Petrozavodsk Camp, Day 2: 300iq Contest 2 (XX Open Cup, Grand Prix of Kazan)// URL: https://codeforces.com/gym/102331/problem/B// Author: yozora0908// Memory Limit: 1024 MB// Time Limit: 2000 ms//// Let's Daze//// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>using namespace std;#define int long long#define uint unsigned long long#define PII pair<int,int>#define MP make_pair#define fi first#define se second#define pb push_back#define eb emplace_back#define SET(a,b) memset(a,b,sizeof(a))#define CPY(a,b) memcpy(a,b,sizeof(b))#define rep(i,j,k) for(int i=(j);i<=(k);++i)#define per(i,j,k) for(int i=(j);i>=(k);--i)int read() { int a=0, f=1; char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) a=a*10+c-'0', c=getchar(); return a*f;}const int N=3e5+5, mod=998244353;int n, k, a[N];int f[N];struct Trie { int tot=1, trie[N*60][2], g[N*60]; void insert(int S,int v) { int x=1; for(int i=59;~i;--i) { int a=(S>>i)&1; if(!trie[x][a]) trie[x][a]=++tot; x=trie[x][a]; (g[x]+=v)%mod; } } int query(int S) { int x=1, res=0; for(int i=59;~i;--i) { int a=(k>>i)&1, b=(S>>i)&1; if(a==0) (res+=g[trie[x][b^1]])%=mod; x=trie[x][a^b]; } if(x) (res+=g[x])%=mod; return res; }} T;signed main() { n=read(), k=read(); rep(i,1,n) a[i]=read(); sort(a+1,a+n+1); f[1]=1; T.insert(a[1],f[1]); rep(i,2,n) { int D=T.query(a[i]); f[i]=(1+D)%mod; T.insert(a[i],f[i]); } int ans=0; rep(i,1,n) (ans+=f[i])%=mod; printf("%lld\n",ans); return 0;}觉得这篇文章怎么样?
点个赞,让更多人看到!

评论区