• 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; }


  • 相关阅读:
    jQuery
    jQuery
    jQuery Callback 函数
    怎样提高团队管理能力4
    poj 3461 Oulipo(KMP模板题)
    每日一小练——按字典顺序列出全部排列
    Java数据结构与算法之排序
    China Vis 2015 会议小结
    网络基础知识小小说
    NS3网络仿真(7): Wifi节点
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7067340.html
Copyright © 2020-2023  润新知