题意:
求出公式的值。
∑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);
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-06 03:44:44