1 2 1 1
12
这题题意容易懂,就是求和,其中(?log2S(i,j)?+1)的意思就是S(i,j)化成二进制后的比特位个数,因为S(i,j)不超过10^10,所以比特位不会超过35个。我们可以先初始化b[],
记录比特位为i的所有数中的最后一个数2^i-1,用sum[i]把从1到i的总和记录下来,然后用35个指针pt[i]记录以i为起点的最大下标k满足sum[k]-sum[i-1]<=b[j]。
最后注意要用G++交,C++会超时。。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define ll long long #define maxn 100060 ll b[50],sum[maxn];//b[1]=2^i-1 ll a[maxn]; int pt[44];//指针 void init() { int i,j; b[0]=-1; b[1]=1; for(i=2;i<=35;i++){ b[i]=(1LL<<i)-1; //也可以是b[i]=((ll)1<<i)-1;,但不加的话会爆int } } int main() { int n,m,i,j,T,len; ll ans; init(); scanf("%d",&T); while(T--) { scanf("%d",&n); sum[0]=0;ans=0; for(i=1;i<=n;i++){ scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; } for(i=1;i<=35;i++)pt[i]=0; for(i=1;i<=n;i++){ pt[0]=i-1; for(j=1;j<=34;j++){ while(sum[pt[j]+1]-sum[i-1]<=b[j] && pt[j]<n){//如果a>b,那么pt[a]一定大于等于pt[b] pt[j]++; } //if(sum[pt[j]]-sum[i-1]>b[j-1] && sum[pt[j]]-sum[i-1]<=b[j] && pt[j]>=i ){ 这一句可以不用写 len=(pt[j]-pt[j-1]); ans+=(ll)j*len*i; ans+=(ll)j*len*(pt[j-1]+1+pt[j])/2; //} } } printf("%lld\n",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/kirito_acmer/article/details/47377305