链接 :http://acm.hdu.edu.cn/showproblem.php?pid=5358
First One
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 871 Accepted Submission(s): 271
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 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).
Output
For each test case, output the value.
Sample Input
1 2 1 1
Sample Output
12
题意:根据那个公式算出 ans。
做法:之前想着 枚举 左端点,再枚举 33个二进制数,再二分右端点来写。 O(33*n *log n) , t掉了。
这题卡时间卡得很严,看了题解后 ,发现有O(33*n)的做法。
显示枚举 33个二进制数, 然后取 num[i] num[j] 作为边界 L,R, 再枚举左端点,左端点遍历的时候 根据LR, 找到 右端点的范围l 和r 要求 L<=s(i,l)<=s(i,r)<R , 左端点不断右移,所以 边界l,r 也不断右移 不用回溯,所以是线性的复杂度为n。
c++还是会T g++可以过。
#include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector> #include<iostream> #include<algorithm> #include<bitset> #include<climits> #include<list> #include<iomanip> #include<stack> #include<set> using namespace std; #define ll __int64 ll num[40]; int aa[100100]; ll sum[100100]; int n; void init() { num[0]=0; num[1]=2; for(int i=2;i<38;i++) { num[i]=num[i-1]*2; } } ll solve(int c,ll L,ll R)//算 大于等于L 小于r的 { ll ans=0; int l,r; r=0; l=0; for(int i=1;i<=n;i++)//枚举起点 { if(r<i-1) r=i-1; if(l<i) l=i; while(l<n&&sum[l]-sum[i-1]<L) l++; while(r<n&&sum[r+1]-sum[i-1]<R) r++; if(r<l) continue; if(sum[l]-sum[i-1]<L) continue; if(sum[r]-sum[i-1]>=R) continue;; ans+=(ll)(c+1)*((ll)(l+r)*(ll)(r-l+1)/2+(ll)i*(ll)(r-l+1)); } return ans; } int main() { init(); int t; scanf("%d",&t); while(t--) { scanf("%d",&n); sum[0]=0; for(int i=1;i<=n;i++) { scanf("%d",aa+i); sum[i]=sum[i-1]+aa[i]; } __int64 ans=0; for(int i=0;i<=33;i++) { ans+=solve(i,num[i],num[i+1]); } printf("%I64d\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。