hdu 5358 First One 数学

链接 :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;
}

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

时间: 2024-10-17 22:59:12

hdu 5358 First One 数学的相关文章

HDU 5358 First One 数学+尺取法

多校的题,摆明了数学题,但是没想出来,蠢爆了,之前算了半天的s[i][j]的和,其实是积.其实比赛的时候我连log(s[i][j])+1是s[i][j]的位数都没看出来,说出来都丢人. 知道了这个之后,就枚举二进制数的每一位,因为元素都是非负数,所以sum数组是非降的,这里用到了尺取法,之前也是听说过,应该是做过吧,不太记得了. 因为[2k-1,2k)的位数是k,枚举时,固定左端点,在sum数组找到最小的大于等于2k-1,最大的小于2k的点,这中间的点和左端点的s[i][j]就对于当前的k满足条

HDU 5358 多校第6场 First One

First One Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 672    Accepted Submission(s): 193 Problem Description soda has an integer array . Let  be the sum of . Now soda wants to know the va

HDU 4816 Bathysphere(数学)(2013 Asia Regional Changchun)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4816 Problem Description The Bathysphere is a spherical deep-sea submersible which was unpowered and lowered into the ocean on a cable, and was used to conduct a series of dives under the sea. The Bathys

HDU 4937 Lucky Number (数学,进制转换)

题目 参考自博客:http://blog.csdn.net/a601025382s/article/details/38517783 //string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[first,last)之间的字符串 /* 题意: 我们将3,4,5,6认为是幸运数字.给定一个十进制数n. 现在可以讲起任意转

HDU 1018 Big Number 数学题解

Problem Description In many applications very large integers numbers are required. Some of these applications are using keys for secure transmission of data, encryption, etc. In this problem you are given a number, you have to determine the number of

hdu 4823 Energy Conversion(数学)

题目链接:hdu 4823 Energy Conversion 题目大意:中文题,不解释. 解题思路:首先判断一下m是否已经大于n了,如果大于那么就是0,假设中间变换的各个值为ai,那么bi=ai+c,bi数组为等比数组(可推),所以就有了cnt=log((n+c)a)log(double(k)),结果为浮点数,需要向上取整. #include <cstdio> #include <cstring> #include <cmath> int main () { int

hdu 4710 Balls Rearrangement (数学思维)

题意:就是  把编号从0-n的小球对应放进i%a编号的盒子里,然后又买了新盒子, 现在总共有b个盒子,Bob想把球装进i%b编号的盒子里.求重置的最小花费. 每次移动的花费为y - x ,即移动前后盒子编号的差值的绝对值. 算法: 题目就是要求                  先判断  n与  lcm(a,b)的大小,每一个周期存在循环,这样把区间缩短避免重复计算. 如果n>lcm(a,b)则   ans = (n/lcm)*solve(lcm)+solve(n%lcm) 否则   ans =

HDU 5358(2015多校联合训练赛1006) First One (区间合并+常数优化)

HDU 5358 题意: 求∑?i=1?n??∑?j=i?n??(?log?2??S(i,j)?+1)?(i+j). 思路: S(i,j) < 10^10 < 2^34,所以log2(S)+1的值只可能在1~35之间.由于log变化缓慢的函数特性,我们可以S(i,n)分作多个相同log值的区间来计算,用pos[i][j]预处理记录每个以i为起点,log(s)值为j的区间的右边界,即可优化至nlogn的复杂度. 主要是写起来比较难一些,一些细节比较纠结,一定思路理清后再写. ps.此题卡常数毫无

HDU 1005 Number Sequence (数学规律)

Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 104190    Accepted Submission(s): 25232 Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A