码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5358 First One 数学

时间:2015-08-07 16:15:23      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:数学题

链接 :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=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
 


题意:根据那个公式算出 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;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 5358 First One 数学

标签:数学题

原文地址:http://blog.csdn.net/u013532224/article/details/47339699

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!