⌊log2S(i,j)⌋+1 就是S(i,j) 的二进制位数.....
枚举二进制的每一位数,计算相应的权值
具体作法就是对每个二进制位数 i ,扫一遍数组,对每个数 j 维护一个L,R 表示以该数为左端点,右端点可以在L~R的范围,这个区间内的值
加起来有 i 位二进制位数,那么这个数对答案的贡献为 设: dur = (R-L+1) 贡献值: dur*j+(R+L)*dur/2
C++秒T , G++ 1.3s ac
First One
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1183 Accepted Submission(s): 357
Problem Description
soda has an integer array
a1,a2,…,an
. Let
S(i,j)
be the sum of
ai,ai+1,…,aj
. Now soda wants to know the value below:
Note: In this problem, you can consider log20 as 0.
∑i=1n∑j=in(⌊log2S(i,j)⌋+1)×(i+j)
Note: In this problem, you can consider log20 as 0.
Input
There are multiple test cases. The first line of input contains an integer
T
, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤105) , the number of integers in the array.
The next line contains n integers a1,a2,…,an (0≤ai≤105) .
The first line contains an integer n (1≤n≤105) , the number of integers in the array.
The next line contains n integers a1,a2,…,an (0≤ai≤105) .
Output
For each test case, output the value.
Sample Input
1 2 1 1
Sample Output
12
Source
/* ***********************************************
Author :CKboss
Created Time :2015年08月07日 星期五 16时48分08秒
File Name :HDOJ5358.cpp
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long int LL;
const int maxn=100100;
int n;
LL s[maxn];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T_T;
scanf("%d",&T_T);
while(T_T--)
{
scanf("%d",&n);
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
s[i]=s[i-1]+x;
}
LL ans=0;
for(int i=0;i<35;i++)
{
/// 在left 和 right 之间的数有(i+1)个1
LL left=(1LL<<i);
LL right=(1LL<<(i+1LL))-1LL;
if(i==0) left=0LL;
int L=1,R=1;
for(int j=1;j<=n;j++)
{
/// Move L
if(L<j) L=j;
while(L<=n&&s[L]-s[j-1]<left) L++;
if(L==n+1) L--;
if(L==n&&s[L]-s[j-1]<left) break;
if(R<L) R=L;
/// Move R
while(R<=n&&s[R]-s[j-1]<=right) R++;
if(R==n+1) R--;
if(s[R]-s[j-1]>right) R--;
LL dur=R-L+1;
ans=ans+(i+1LL)*(dur*j+(R+L)*dur/2LL);
}
}
cout<<ans<<endl;
}
return 0;
}