hdu5358 First One

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

这题题意容易懂,就是求和,其中(?log2S(i,j)?+1)的意思就是S(i,j)化成二进制后的比特位个数,因为S(i,j)不超过10^10,所以比特位不会超过35个。我们可以先初始化b[],

记录比特位为i的所有数中的最后一个数2^i-1,用sum[i]把从1到i的总和记录下来,然后用35个指针pt[i]记录以i为起点的最大下标k满足sum[k]-sum[i-1]<=b[j]。

最后注意要用G++交,C++会超时。。
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
#define ll long long
#define maxn 100060
ll b[50],sum[maxn];//b[1]=2^i-1
ll a[maxn];
int pt[44];//指针
void init()
{
	int i,j;
	b[0]=-1;
	b[1]=1;
	for(i=2;i<=35;i++){
		b[i]=(1LL<<i)-1; //也可以是b[i]=((ll)1<<i)-1;,但不加的话会爆int
	}
}
int main()
{
	int n,m,i,j,T,len;
	ll ans;
	init();
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		sum[0]=0;ans=0;
		for(i=1;i<=n;i++){
			scanf("%lld",&a[i]);
			sum[i]=sum[i-1]+a[i];
		}
		for(i=1;i<=35;i++)pt[i]=0;
		for(i=1;i<=n;i++){
			pt[0]=i-1;
			for(j=1;j<=34;j++){
				while(sum[pt[j]+1]-sum[i-1]<=b[j] && pt[j]<n){//如果a>b,那么pt[a]一定大于等于pt[b]
					pt[j]++;
				}
				//if(sum[pt[j]]-sum[i-1]>b[j-1] && sum[pt[j]]-sum[i-1]<=b[j] && pt[j]>=i ){ 这一句可以不用写
					len=(pt[j]-pt[j-1]);
					ans+=(ll)j*len*i;
					ans+=(ll)j*len*(pt[j-1]+1+pt[j])/2;
				//}
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

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

时间: 2024-11-05 23:31:56

hdu5358 First One的相关文章

hdu5358 First One(尺取法)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud First One Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1158    Accepted Submission(s): 347 Problem Description soda has an integer

[hdu5358]分类统计,利用单调性优化

题意:直接来链接吧http://acm.hdu.edu.cn/showproblem.php?pid=5358 思路:注意S(i,j)具有区间连续性且单调,而⌊log2x⌋具有区间不变性,于是考虑枚举⌊log2S(i,j)⌋的值,然后枚举i,从而能得到j的区间范围,然后统计答案即可. 另外这题比较坑,先枚举 ⌊log2S(i,j)⌋再枚举i 老是TLE,加了各种常数优化还是TLE,换成先枚举i再枚举⌊log2S(i,j)⌋就过了. 1 2 3 4 5 6 7 8 9 10 11 12 13 14

[数学]hdu5358

题意: 求出公式的值. ∑i=1n∑j=in(?log2S(i,j)?+1)×(i+j) 分析: 主要是看到二进制的特点 log2(s)+1其实就是s二进制的位数.那么只需要求出所有区间的边界和乘上区间和的位数就好了.注意这里的数据量100000,所以s最大不超过35位,那么我们可以枚举位数,然后遍历左区间j,求出所有满足条件的r,即j,j+1,--..r,r+1,-.R(r–R 都是满足条件的) 然后计算结果就可以了. //美妙的数学 #include<iostream> #include&