码迷,mamicode.com
首页 > 其他好文 > 详细

[数学]hdu5358

时间:2015-08-25 16:52:22      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:数学

题意:
求出公式的值。
∑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 都是满足条件的) 然后计算结果就可以了。

//美妙的数学 


#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[n]<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);
    }

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

[数学]hdu5358

标签:数学

原文地址:http://blog.csdn.net/u010582475/article/details/47976409

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!