hdu5358First One

First One

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 949    Accepted Submission(s): 288


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=1nj=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  (1n105), the number of integers in the array.
The next line contains  n integers  a1,a2,,an  (0ai105).
 

Output
For each test case, output the value.
 

Sample Input
 
   
1 2 1 1
 

Sample Output
 
   
12
 
数学题,方法
s(i,j)在[2^(k-1),2^k)之间时 log2(s(i,j))下取整+1的值是k,枚举k从1到34 ,求出对应的s(i,j)在[2^(k-1),2^k)之间时i+j的和,求这个的话,可以枚举起始点从1到n,用两个指针不断后移
 
   

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
typedef long long ll;
using namespace std;
ll n,t,a[100005],sum[100005];
ll solve(ll L,ll R){
ll i,l,r;
ll ans=0;
r=0;l=1;
for(i=1;i<=n;i++){
if(l<i) l=i;
if(r<i-1) r=i-1;
while(l<n&&sum[l]-sum[i-1]<L) l++;
while(r+1<=n&&sum[r+1]-sum[i-1]<R) r++;
if(l>r) continue;
if(sum[r]-sum[i-1]<L || sum[r]-sum[i-1]>=R) continue;
if(sum[l]-sum[i-1]<L || sum[l]-sum[i-1]>=R) continue;
ans+=(r-l+1)*i+(l+r)*(r-l+1)/2;
}
return ans;
}
int main(int argc, char *argv[])
{
ll i;
cin>>t;
while(t--){
scanf("%lld",&n);
sum[0]=0;
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
}
ll num[35];
memset(num,0,sizeof(num));
num[0]=solve(0,1);
for(i=1;i<=34;i++){
ll l=pow(2.0,(int)i-1);
ll r=pow(2.0,(int)i);
num[i]=solve(l,r);
}
ll ans=0;
for(i=1;i<=34;i++) ans+=num[i]*i;
ans+=num[0];
//for(i=0;i<=34;i++) cout<<num[i]<<" ";
printf("%lld\n",ans);
}
return 0;
}



猜你喜欢

转载自blog.csdn.net/nature_ran/article/details/79125331
one