接下来升级 k 和 g,就直接让 k 变成 k+1,g 变成 g \times 2 即可。还可以发现 k 其实是没有用的,所以可以直接用 g 来做循环变量,从 2 开始,依次 \times 2。
对了,那这个 g 枚举到什么时候就打断循环呢?如果设 mx 为 a_i 中的最大值,那么这个 g 只要不超过 mx \times 2,就可以继续,超过了就跳出循环。
为什么?因为 mx 是最大的呀,它自己和自己相加一定是和里边最大的了吧。如果 g 都超过 mx 自己和自己相加,也就是 mx \times 2 了,那还能有哪个两个数之和会是 g 的倍数呢?这就没有枚举的必要了呀,所以是这个限制。
说到现在,你一定知道怎么做了,代码编起来很简单,就别看我的了吧!不过,我还是会把代码贴上哟。
代码
注意代码里的 k 其实指的就是思路里所说的 g,其他变量名都统一。随你怎么看吧!
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5 , M = 2e7+5;
long long n,a[N],cnt[M],sum[M],mx,ans;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];mx=max(mx,a[i]);
ans+=a[i]*(n-1);
long long tmp=a[i];
while(tmp%2==0)tmp/=2;
ans+=tmp;
}
for(int k=2;k<=mx*2;k*=2){
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++){
int zm=a[i]%k,fm=(k-a[i]%k)%k;
if(cnt[fm])ans-=(sum[fm]+cnt[fm]*a[i])/k;
cnt[zm]++,sum[zm]+=a[i];
}
}
cout<<ans;
return 0;
}