您的位置:首页 > 其它

[数学]hdu5358

2015-08-25 14:17 447 查看
题意:

求出公式的值。

∑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 都是满足条件的) 然后计算结果就可以了。

[code]//美妙的数学 

#include<iostream>   
#include<stdio.h>  
#include<math.h>  
#include<utility>
#include <map>
#include<cstring>
#include<vector>
#include<deque>
#include<queue>
#include<stack>
#include<algorithm> 
#include<stdlib.h>  
#define read freopen("q.txt","r",stdin) 
#define LL long long 
const int maxn =100005;
const int inf=2000000000;
LL pl[40],pr[40],s[maxn];
void init()
{
    int i,j;

    for(i=1;i<40;i++)
    {
        pl[i]=(1ll<<i);
        pr[i]=(1ll<<(i+1))-1;
    }
    pl[0]=0;pr[0]=1;
}

int main()
{
    LL i,j,cas,n;
    init();
    scanf("%I64d",&cas);
    while(cas--)
    {
        LL a,res=0;
        memset(s,0,sizeof(s));
        scanf("%I64d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%I64d",&a);
            s[i]=s[i-1]+a;
        }
        for(i=1;i<=35;i++)
        {
            if(s
<pl[i-1])break;
            LL L=1,R=0,tmp=0;
            for(j=1;j<=n;j++)
            {
                L=L>j?L:j;
                while(s[L]-s[j-1]<pl[i-1] && L<=n)L++;
                R=R>L-1?R:L-1;
                while(s[R+1]-s[j-1]>=pl[i-1]&& s[R+1]-s[j-1]<=pr[i-1] && R+1<=n)R++;
                if(R>=L)
                {
                    tmp+=(LL)(R-L+1)*j+(R-L+1)*(R+L)/2;
                }
            }
            res+=tmp*i;
        }
        printf("%I64d\n",res);
    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: