P10114-题解
题意简述:
给出一个长度为
其中定义
对于所有数据,
核心思路:
定义
Sub1
特殊性质:所有的
输出
void sub1(){
cout<<(long long)n*n<<endl;
return;
}
Sub2
数据特点:
int ABS(int x){
return x<0?-x:x;
}
int num(int x){
int cnt=0;
while(x){
if(x&1)cnt++;
x>>=1;
}
return cnt;
}
void sub2(){
ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
ans+=num(d[i]+d[j])+num(ABS(d[i]-d[j]));
}
}
cout<<ans<<endl;
return;
}
Sub3
特殊性质:
开始动脑子,因为
-
如果
d_i=2^k,d_j=2^{k'} 且k\ne k' 。那么\operatorname{num}(d_i+d_j) 的值必然为2 。因为d_i,d_j 在二进制下只有一个1 ,且1 的位置不相同。 -
如果
d_i=2^k,d_j=2^{k'} 且k=k' 。那么\operatorname{num}(d_i+d_j) 的值必然为1 。因为d_i,d_j 在二进制下只有一个1 ,且1 的位置相同。相加进位后原来的两个1 会进位成一个新的1 。 -
如果
d_i=2^k,d_j=2^{k'} 且k=k' 。那么\operatorname{num}(\operatorname{abs}(d_i-d_j)) 的值必然为0 。两个相等的数差为0 ,二进制下1 的个数自然为0 -
如果
d_i=2^k,d_j=2^{k'} 且k\ne k' 。那么\operatorname{num}(\operatorname{abs}(d_i-d_j)) 的值必然为\operatorname{abs}(k-k') 。可以自己举几个例子尝试一下。
用一个数组
前面这一堆是上述
后面一堆则是
void sub3(){
long long res=0,len=0;
for(int i=1;i<=n;i++)mk[(int)log2(d[i])]++,len=max((long long)log2(d[i]),len);
for(int i=0;i<=len;i++)res+=1ll*mk[i]*(2*n-mk[i]);
for(int i=0;i<=len;i++){
for(int j=0;j<=len;j++){
res+=1ll*(mk[i]*mk[j]*ABS(i-j));
}
}
printf("%lld\n",res);
return;
}
Sub4
令
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int N=5e7+10;
int n,mk[N],x;
vector<int>v;
long long ans=0;
int ABS(int x){
return x<0?-x:x;
}
int num(int x){
int cnt=0;
while(x){
if(x&1)cnt++;
x>>=1;
}
return cnt;
}
int main(){
scanf("%d",&n);
v.push_back(0);
for(int i=1;i<=n;i++){
scanf("%d",&x);
if(!mk[x])v.push_back(x);
mk[x]++;
}
for(int i=1;i<v.size();i++){
for(int j=1;j<v.size();j++){
ans+=(long long)mk[v[i]]*mk[v[j]]*(num(v[i]+v[j])+num(ABS(v[i]-v[j])));
}
}
cout<<ans<<endl;
return 0;
}
枚举不同种类数的两层循环复杂度