zoukankan      html  css  js  c++  java
  • HDU 5358 尺取法+枚举

    题意:给一个数列,按如下公式求和。

    分析:场上做的时候,傻傻以为是线段树,也没想出题者为啥出log2,就是S(i,j) 的二进制表示的位数。只能说我做题依旧太死板,让求和就按规矩求和,多考虑一下就能发现这个题目应该是另想办法解决的,类似于改代码的题目,直接告诉你C++代码,让你从TLE改成AC,其实真正让你改的是算法,全身都要变。

    看了题解,终于明白这道题目的正解算法:

    因为S(i,j)的位数在一定范围内是一样的,所以我们可以枚举位数1~35(顶多是2^34),怎么计算(i+j)?继续枚举起点k,然后找满足位数是所枚举的位数的区间(l,r)即(k,l)~(k,r)都是二进制位数为t的,然后统一计算(k,l)~(k.r)的和,其实就是一个l~r的等差序列(r + l)*(r - l + 1) / 2,一个是k的(r-l+1)倍。一直枚举到位数大于数列全部的和。

    PS:枚举区间的时候用的是尺取法,很容易懂,就是从起点k开始,直到有不满足的条件,否则l++,然后r直接从l开始,其实计算的时候一般能想得到。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 #define LL long long
     6 #define maxn 101010
     7 LL pow2l[50],pow2r[50],s[maxn];
     8 int main()
     9 {
    10     for(int i=1; i<=40; i++)
    11     {
    12         pow2l[i]=(1ll<<i);
    13         pow2r[i]=((1ll<<(i+1))-1);
    14     }
    15     pow2l[0]=0;
    16     pow2r[0]=1;
    17     LL ncase,i,j,n,x;
    18     scanf("%I64d",&ncase);
    19     while(ncase--)
    20     {
    21         scanf("%d",&n);
    22         for(i=1; i<=n; i++)
    23         {
    24             scanf("%I64d",&x);
    25             s[i]=s[i-1]+x;
    26         }
    27         LL ans=0;
    28         for(i=1; i<=35; i++)
    29         {
    30             if(s[n] < pow2l[i-1])
    31                 break;
    32             LL l=1,r=0,temp=0;
    33             for(j=1; j<=n; j++)
    34             {
    35                 l = max(l,j);
    36                 while(l <= n && s[l] - s[j-1] < pow2l[i-1])
    37                     l++;
    38                 r = max(r,l - 1);
    39                 while(r < n && s[r+1] - s[j-1] >= pow2l[i-1] && s[r+1]-s[j-1] <= pow2r[i-1])
    40                     r++;
    41                 if(r >= l)
    42                     temp+=(r-l+1)*j+(r+l)*(r-l+1)/2;
    43             }
    44             ans += temp * i;
    45         }
    46         printf("%I64d
    ",ans);
    47     }
    48     return 0;
    49 }
    AC
  • 相关阅读:
    Appium遇到的问题二(持续更新....)
    开源unittest测试报告源码BSTestRunner.py
    Unittest + python
    python快速开发Web之Django
    Python基础(五) python装饰器使用
    Appium环境搭建(一)
    linux ssh 报错failed
    CentOS6.9快速安装配置svn
    python 购物车小程序
    连续三次登陆失败锁定账户
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4720140.html
Copyright © 2011-2022 走看看