ARC127D Sum of Min of Xor
性质分析加通用套路。
思路
首先我们把这题的 \(\min\) 给去掉,那么我们按位算贡献,可以求出和。这是这种式子的通用套路。
考虑加上 \(\min\),那么我们先按照 \((a_i,b_i)\) 的最高位分为:\((1,0)\),\((0,1)\),\((1,1)\),\((0,0)\) 四种情况。
可以发现用贡献的组如下:
- \((0,0)\),\((0,1)\) 贡献为 \(a_i\oplus a_j\)。
- \((0,0)\),\((1,0)\) 贡献为 \(b_i\oplus b_j\)。
- \((1,1)\),\((1,0)\) 贡献为 \(a_i\oplus a_j\)。
- \((1,1)\),\((0,1)\) 贡献为 \(b_i\oplus b_j\)。
- \((1,1)\),\((1,1)\) 贡献需要向下枚举一位计算。
- \((0,0)\),\((0,0)\) 贡献需要向下枚举一位计算。
那么已知贡献的我们可以用通用套路算,不知道的向下枚举即可。
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define K 18
const int maxn=3e5+5;
int n;
int a[maxn],b[maxn];
ll ans;
vector<int>sd;
void C(vector<int> &d1,vector<int> &d2,bool w)
{
for(int i=0;i<K;i++)
{
int c1,c2;
c1=c2=0;
for(int j:d1) c1+=(w?b[j]:a[j])>>i&1;
for(int j:d2) c2+=(w?b[j]:a[j])>>i&1;
ans+=(1ll*c1*(d2.size()-c2)+1ll*c2*(d1.size()-c1))<<i;
}
}
void S(int p,vector<int> &d)
{
if(d.empty()) return ;
if(p==-1)
{
for(int i=0;i<K;i++)
{
int c1=0;
for(int j:d)
c1+=a[j]>>i&1;
ans+=1ll*c1*(d.size()-c1)<<i;
}
return ;
}
vector<int> l[2][2];
for(int i:d) l[a[i]>>p&1][b[i]>>p&1].push_back(i);
C(l[0][0],l[0][1],0);
C(l[0][0],l[1][0],1);
C(l[1][1],l[0][1],1);
C(l[1][1],l[1][0],0);
for(int i:l[0][0]) l[1][1].push_back(i);
for(int i:l[0][1]) l[1][0].push_back(i);
S(p-1,l[1][1]),S(p-1,l[1][0]);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),sd.push_back(i);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
S(K-1,sd);
printf("%lld",ans);
}
标签:Xor,Min,int,Sum,贡献,oplus,c1
From: https://www.cnblogs.com/binbinbjl/p/17988643