cf--Subarrays Beauty

题目地址: 点击打开链接
题意: Beauty(l, r) = al & al + 1 & al + 2 & ... & ar     求给定集合的任意连续子集合的Beauty(l, r) 的和
思路:一个数一个数往上加,ss[i][j]记录前面i个数,以第i个数结尾的子区间的各个&的二进制右数第j个位置的1的个数,与新加入的数按位同为1时才保留,所以二进制一位一位判断,新加入的数的二进制对应为1的位置与ss[i][j]个数求和、说的不太明白。。还是看代码比较好理解

感想:一开始看着这个题就觉得不能做,然后就做别的题,后来有别的队的A了,然后才回来看的这个题。。。好不容易想出来了方法,感觉有点思维,有点推规律、不过感觉这个题还是挺有意思的,值得写篇博客记录一下
代码:
 
 
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f;
#define mod 1000000007
long long n,T,ans,a[100005],x,ss[100005][25],k,pp[30];
int main()
{ 
    pp[0]=1; 
    for(int i=1;i<=20;i++) 
    { 
        pp[i]=pp[i-1]*2;//预处理二进制各位在十进制中代表的数 
    } 
    scanf("%lld",&T); 
    while(T--) 
    { 
        memset(ss,0,sizeof(ss));
        ans=0;
        scanf("%lld",&n); 
        for(int i=1;i<=n;i++) 
        {
            scanf("%lld",&a[i]); 
            ans+=a[i]; 
        } 
        for(int i=1;i<=n;i++) 
        { 
            x=a[i]; 
            for(int j=0;j<=20;j++) 
            { 
                if(ss[i-1][j]!=0&&(x&1)) 
                {//前面的以i-1位置结尾的区间的&里,二进制右面j位置也有为1的,所以与新加入的i位置的数&,第j位的值仍为1.
                ss[i][j]=ss[i-1][j];
                ans+=pp[j]*ss[i-1][j]; } 
                if(x&1) ss[i][j]++; x>>=1; //cout<<i<<" "<<j<<" "<<ss[i][j]<<" "<<ans<<endl; 
                if(x==0) break; 
            }
        }
        printf("%lld\n",ans);
    }
}



猜你喜欢

转载自blog.csdn.net/qq_37868325/article/details/80294582