HDU 5358 First One(枚举)
2015-08-07 11:46
351 查看
First One
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 690 Accepted Submission(s): 205
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
Source
2015 Multi-University Training Contest 6
题目大意:对题目中的式子求结果。
解题思路:因为0<=ai<=10^5,0<n<=10^5,所以0<=S(i,j)<10^12<2^34,设k=⌊log2S(i,j)⌋+1则1<=k<=34,那么我们
每次枚举k时,求解出所有符合条件的(i+j),求和即可。
而对于每一个k,求解(i+j)时,先预处理出s[i](s[i]=a1+……+ai,则sum(i,j)=s[j]-s[i-1]),那么接下来只需找到所有
满足2^(k-1)<=sum(i,j)<=2^k-1的(i+j)即可。
对于求(i+j),我们再次枚举i,对每一个i,求解出j的一个区间[l,r],使得对当前的i,有当l<=j<=r时,2^(k-1)
<=sum(i,j)<=2^k-1成立。那么对于当前的k,i,满足条件的i,j区间为[i,j](l<=j<=r),这些区间对应同一个k和同一个i,这些区间的(i+j)的总和为:i*(r-l+1)+(r+l)*(r-l+1)/2。
枚举完所有的k和i,将所有和累加。
对于求解区间[l,r],假设k=a,在枚举i=b时,得到j的区间[L1,R1],那么相同的k,在枚举i=b+1时,得到j的区间[L2,R2]
一定不在区间[L1,R1]的左边,简单的说就是L2>L1,R2>R1。因此查找l,r时可以减少范围。
代码如下:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> #include <string> #include <vector> #include <deque> #include <list> #include <set> #include <map> #include <stack> #include <queue> #include <numeric> #include <iomanip> #include <bitset> #include <sstream> #include <fstream> #include <limits.h> #define debug "output for debug\n" #define pi (acos(-1.0)) #define eps (1e-6) #define inf (1<<28) #define sqr(x) (x) * (x) #define mod 1000000007 using namespace std; typedef long long ll; typedef unsigned long long ULL; ll fl[35]={0,0,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592}; ll fr[35]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287,1048575,2097151,4194303,8388607,16777215,33554431,67108863,134217727,268435455,536870911,1073741823,2147483647,4294967295,8589934591,17179869183}; ll s[100005]; int main() { ll i,j,k,n,a,l,r,t; scanf("%I64d",&t); while(t--) { scanf("%I64d",&n); for(i=1;i<=n;i++) { scanf("%I64d",&a); s[i]=s[i-1]+a; } ll ans=0; for(k=1;k<=34;k++) { l=1; r=0; //移位操作控制sum(i,j)的范围,也可以用数组 //fl= k==1?0:(1ll<<(k-1));fr=(1ll<<k)-1; for(i=1;i<=n;i++) { l=max(i,l); while(l<=n&&s[l]-s[i-1]<fl[k])//while(l<=n&&s[l]-s[i-1]<fl) l++; r=max(l-1,r); while(r+1<=n&&s[r+1]-s[i-1]>=fl[k]&&s[r+1]-s[i-1]<=fr[k])//while(r+1<=n&&s[r+1]-s[i-1]>=fl[k]&&s[r+1]-s[i-1]<=fr) r++; if(l<=r) ans+=(i*(r-l+1)+(r+l)*(r-l+1)/2)*k; //ans+=(i+l+i+r)*(r-l+1)/2*k; } } printf("%I64d\n",ans); } return 0; }
相关文章推荐
- SVN图标不见了?
- 49. Element removeAttribute() 方法
- 关于json解析
- codeforces#314D&567D One-Dimensional Battle Ships (Set)
- 比特、字节转换
- [转] 淘宝数据库分布式代理层TDDL剖析
- Aspose.Cells.dll的运用
- Linux系统用户账号管理
- PHP 实现文件强制下载
- TCP--SYN洪水攻击
- 互联网公司2014前端笔试面试题:HTML/CSS篇
- JavaBean基本概念
- PHP的array_map函数使用类内部方法作为回调函数的实现方式
- 【细说PHP学习】第十八章 MySQL数据表的设计
- 2015暑假训练赛个人赛(8.7)
- Mac下配置Apache服务
- D4
- [转载]x86/x86-64/x64/AMD64/IA64/Intel64
- C++ 静态全局变量与普通全局变量
- hdoj 5001 概率dp