cf--Subarrays Beauty

本文介绍了一种解决特定子区间Beauty和问题的方法。通过记录每个子区间按位与操作的结果,逐步累加并更新最终答案。算法巧妙利用二进制特性,实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

题目地址:点击打开链接

题意: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);
    }
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值