题意很简单,就是把[1,n]中能用2的幂的形式表示的变成负数,然后再相加;
很显然
1.1–n等差数列求和;
2.用等比数列求出公比为2,首项为1的和;
一看1e9次方,枚举爆表,所以巧妙枚举,利pow(2,i)<=n来找出其中的值;
这里用快速幂加速:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll QM(ll x,ll n){//快速幂
ll res=1;
while(n){
if(n&1){
res=res*x;
}
x*=x;
n>>=1;
}
return res;
}
int main(){
ll T,n;
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
ll ans=0,t;
for(int i=0;QM(2,i)<=n;i++){
ans+=QM(2,i);//求[1,n]里面能被2的幂表示的数的和
}
printf("%lld\n",n*(n+1)/2-2*ans);//注意ans*2因为1+2+3+4 - 2*(-1-2-4)减去2的幂的和的两倍,也可以用容斥来理解
}
return 0;
}