有一个神奇的结论 \(\forall a<b<c , a \oplus c > min(a \oplus b,b \oplus c)\)
然后就可以写出 \(n^2\) dp,再用TRIE树优化即可
code
#include<bits/stdc++.h>
using namespace std;
#define N 200005
#define int long long
int n,k1,k2;
int a[N],fl[2];
const int mod=1e9+7;
void mo(int &x){
if(x>=mod) x-=mod;
}
struct TRIE{
int tot;
int ch[N*60][2],sum[N*60];
TRIE(){tot=1;memset(ch,0,sizeof(ch));}
void clear(){
while(tot) ch[tot][0]=ch[tot][1]=sum[tot]=0,tot--;
tot=1;
}
void ins(int x,int y){
int p=1;sum[1]+=y;
for(int i=59;i>=0;i--){
int c=(x>>i)&1;
if(!ch[p][c]) ch[p][c]=++tot;
p=ch[p][c],sum[p]+=y,mo(sum[p]);
}
}
int find(int x,int y){
int p=1,ans=0;
for(int i=59;i>=0;i--){
int c1=(x>>i)&1,c2=(y>>i)&1;
if(!c2) ans+=sum[ch[p][c1^1]],mo(ans),p=ch[p][c1];
else p=ch[p][c1^1];
}
return ans+sum[p];
}
}T[2];
signed main(){
//freopen("sabzeruz5.in","r",stdin);
scanf("%lld%lld%lld",&n,&k1,&k2);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+1+n);
fl[0]=fl[1]=1;
for(int i=2;i<=n;i++){
int cnt0=T[1].find(a[i],k1);
int cnt1=T[0].find(a[i],k2);
//printf("%lld %lld\n",cnt0,cnt1);
if((a[i]^a[i-1])<k1) T[0].clear();
if((a[i]^a[i-1])<k2) T[1].clear();
T[0].ins(a[i-1],cnt0),T[1].ins(a[i-1],cnt1);
T[0].ins(a[i-1],fl[1]);T[1].ins(a[i-1],fl[0]);
if((a[i]^a[i-1])<k1) fl[0]=0;
if((a[i]^a[i-1])<k2) fl[1]=0;
}
printf("%lld\n",(T[0].sum[1]+T[1].sum[1])%mod);
return 0;
}
标签:2024.2,27,int,题解,sum,tot,ch,ans,c1
From: https://www.cnblogs.com/hubingshan/p/18038500