zoukankan      html  css  js  c++  java
  • HDU 5358 First One(枚举)

    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=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
     

    Source
     


    题目大意:对题目中的式子求结果。


    解题思路:由于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
    "
    #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 ",ans); } return 0; }


  • 相关阅读:
    [转载]在sharepoint里增加PDF图标显示收藏主题
    CuratorFramework开源Zookeeper快速开发框架介绍
    Zookeeper和CuratorFramework实践之:分布式消息队列
    Zookeeper和CuratorFramework实践系列之: 配置管理
    JS 文字向上滚动代码
    sql递归查询问题
    双线单IP和双线双IP机房的区别
    js获取标准北京时间
    ftp 21端口被占用解决办法
    "由于没有远程桌面授权服务器可以提供许可证..."不能远程桌面解决方法
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7067340.html
Copyright © 2011-2022 走看看