First One
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 142 Accepted Submission(s): 37
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:
∑i=1n∑j=in(⌊log2S(i,j)⌋+1)×(i+j)
Note: In this problem, you can considerlog20 as
0.
Note: In this problem, you can consider
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 integern (1≤n≤105) ,
the number of integers in the array.
The next line containsn integers a1,a2,…,an (0≤ai≤105) .
The first line contains an integer
The next line contains
Output
For each test case, output the value.
Sample Input
1 2 1 1
Sample Output
12
Source
能够枚举每一个位置为開始位置,然后枚举每一个log(sum)仅仅需36*n的。
中间j的累加和
推公式就可以。
可是找log值同样的区间,须要用log(sum)*n的复杂度预处理出来,假设每次二分位置会超时。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define ll long long #define maxn 100007 ll num[maxn]; ll pos[maxn][36]; int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); for(int i = 0;i < n; i++){ scanf("%I64d",&num[i]); } num[n] = 0; for(ll i = 0;i < 36; i++){ ll di = 1LL<<(i+1); ll su = num[0]; int p = 0; for(int j = 0;j < n; j++){ if(j) su -= num[j-1]; while(su < di && p < n){ su += num[++p]; } pos[j][i] = p; } } ll ans = 0,res; for(int i = 0;i < n; i++){ ll p = i,q; for(int j = 0;j < 36 ;j ++){ q = pos[i][j]; res = (j+1)*((i+1)*(q-p)+(p+q+1)*(q-p)/2); ans += res; p = q; } } printf("%I64d ",ans); } return 0; }