First One
题意:数列a中S[i, j]表示,求出下面式子的值:
,其中的 (二式)是向下取整;
根据题目数据,S(i, j)最大不超过2^34,所以二式的范围是[1, 34]令k=二式;
我们可以枚举k的值,尺取法选择区间[l, r]满足k的;
固定i,找j满足的区间[l, r],则在区间中的(i+j)=i*(r-l+1)+(r-l+1)*(r+l)/2;最后再乘k;
#include <bits/stdc++.h>
using namespace std;
long long sum[100010];
int main(){
int T;
scanf("%d", &T);
while(T--){
sum[0]=0;
int n;
long long x;
scanf("%d", &n);
for(int i=1; i<=n; i++){
scanf("%lld", &x);
sum[i]=sum[i-1]+x;
}
long long ans=0;
for(int k=1; k<=34; k++){
long long L=1LL << (k-1), R=(1LL << k) - 1;
if(k==1) L=0;
long long l=1, r=0;
for(int i=1; i<=n; i++){
l=max((long long)i, l);
while(sum[l]-sum[i-1]<L&&l<=n) l++;
r=max(r, l-1);
while(sum[r+1]-sum[i-1]>=L&&sum[r+1]-sum[i-1]<=R&&r+1<=n) r++;
if(l>r) continue;
ans+=(i*(r-l+1)+(r+l)*(r-l+1)/2)*k;
}
}
printf("%lld\n", ans);
}
return 0;
}