铁一中模拟赛2018.11.1 T1

本文详细解析洛谷月赛P3794题目的解题思路与算法实现,通过分析数组中特定条件下的对数计数,利用ST表、二分查找和位运算解决复杂问题。

题目:

(Luogu月赛P3794)

给你一个长度为N的数组a,求有多少对i<=j满足 g c d ( a i , a i + 1 , a i + 2 , . . . , a j ) x o r ( a i o r a i + 1 o r a i + 2 o r . . . a j ) = k gcd(a_i,a_{i+1},a_{i+2},...,a_j)xor(a_i or a_{i+1} or a_{i+2} or ... a_j) =k gcd(ai,ai+1,ai+2,...,aj)xor(aiorai+1orai+2or...aj)=k

注: x o r , o r xor,or xor,or都指位运算

数据范围: n ≤ 500000 , 1 ≤ a [ i ] ≤ 500000 n\le 500000,1\le a[i]\le 500000 n500000,1a[i]500000

题解:

这个题思维难度其实不高主要是要:

  1. 有一个意识(也可以说是套路):求多个数的gcd时,添加一个数,gcd要么不变,要么降低,且最多降低 l o g n log n logn次就变成1

  2. 会二分求出像这样的单调函数的每个断层:

  3. 会灵活运用st表

显然说到这这题也就没什么可做的了,用st表维护区间Gcd和Or值。对于每个区间左端点,Gcd的值都为单调递减断层函数(且最多有log n个断层),Or的值都为单调递增断层函数。直接枚举区间左端点,二分求出Gcd的每个断层,因为 G c d x o r O r = k Gcd xor Or=k GcdxorOr=k,所以 O r = k G c d Or=k^Gcd Or=kGcd,就可以二分找到每个Gcd断层对应的Or断层,然后根据两个断层统计答案即可。

时间复杂度: O ( n l o g 2 n ) O(nlog^2 n) O(nlog2n)

代码:

#include <iostream> 
#include <stdio.h>
#include <algorithm>
using namespace std;
#define N 500005
int n,k;
int ai[N],Gcd[N][25],Or[N][25],Log[N];
long long ans;

inline int getGcd(int x,int y) //O(1)求[x,y]的Gcd
{
    int a=Log[y-x+1];
    return __gcd(Gcd[x][a],Gcd[y-(1<<a)+1][a]);
}

inline int getOr(int x,int y) //O(1)求[x,y]的Or 
{
    int a=Log[y-x+1];
    return (Or[x][a]|Or[y-(1<<a)+1][a]);
}

int main()
{
    scanf("%d%d",&n,&k);
    int np=0;
    for(int i=1;i<=n;i++){
        if(i==(1<<np))
            Log[i]=np++;
        else
            Log[i]=np-1;
    }
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        Or[i][0]=Gcd[i][0]=x;
    }
    for(int a=1;a<=20;a++)
        for(int i=1;i+(1<<a)-1<=n;i++)
        {
            Gcd[i][a]=__gcd(Gcd[i][a-1],Gcd[i+(1<<(a-1))][a-1]);
            Or[i][a]=Or[i][a-1]|Or[i+(1<<(a-1))][a-1];
        }
    for(int now=1;now<=n;now++){ //固定左指针为now
        int nowGcd=Gcd[now][0],rpGcd=now; //now为目前右指针范围到左指针的值,rp为目前右指针范围的左边界
        while(true)
        {
            int l=rpGcd,r=n;
            while(l<r) //二分Gcd右指针范围的右边界 (Gcd右指针递减)
            {
                int mid=((l+r)>>1);
                if(r==l+1) mid++;
                int tnGcd=getGcd(now,mid);
                if(tnGcd<nowGcd)
                    r=mid-1;
                else
                    l=mid;
            }
            int nowOr=(k^nowGcd),yoGcd=l,rpOr,yoOr;
/**/
            l=now,r=n;
            while(l<r) //二分Or右指针范围的左边界 (Or右指针递增)
            {
                int mid=((l+r)>>1);
                int tnOr=getOr(now,mid);
                if(tnOr>nowOr)
                    r=mid-1;
                else if(tnOr==nowOr)
                    r=mid;
                else
                    l=mid+1;
            }
            rpOr=l,r=n;
            while(l<r) //二分Or右指针范围的右边界 (Or右指针递增)
            {
                int mid=((l+r)>>1);
                if(r==l+1) mid++;
                int tnOr=getOr(now,mid);
                if(tnOr>nowOr)
                    r=mid-1;
                else
                    l=mid;
            }
            yoOr=l;
            int zuo=max(rpGcd,rpOr),you=min(yoGcd,yoOr);
            if(you>=zuo && getOr(now,rpOr)==nowOr) ans+=you-zuo+1;
            rpGcd=yoGcd+1;
            if(rpGcd>n) break;
            nowGcd=getGcd(now,rpGcd);
        }
    }
    cout<<ans<<endl;
        
    return 0;
}
内容概要:本文档是一份关于交换路由配置的学习笔记,系统地介绍了网络设备的远程管理、交换机与路由器的核心配置技术。内容涵盖Telnet、SSH、Console三种远程控制方式的配置方法;详细讲解了VLAN划分原理及Access、Trunk、Hybrid端口的工作机制,以及端口镜像、端口汇聚、端口隔离等交换技术;深入解析了STP、MSTP、RSTP生成树协议的作用与配置步骤;在路由部分,涵盖了IP地址配置、DHCP服务部署(接口池与全局池)、NAT转换(静态与动态)、静态路由、RIP与OSPF动态路由协议的配置,并介绍了策略路由和ACL访问控制列表的应用;最后简要说明了华为防火墙的安全区域划分与基本安全策略配置。; 适合人群:具备一定网络基础知识,从事网络工程、运维或相关技术岗位1-3年的技术人员,以及准备参加HCIA/CCNA等认证考试的学习者。; 使用场景及目标:①掌握企业网络中常见的交换与路由配置技能,提升实际操作能力;②理解VLAN、STP、OSPF、NAT、ACL等核心技术原理并能独立完成中小型网络搭建与调试;③通过命令示例熟悉华为设备CLI配置逻辑,为项目实施和故障排查提供参考。; 阅读建议:此笔记以实用配置为主,建议结合模拟器(如eNSP或Packet Tracer)动手实践每一条命令,对照拓扑理解数据流向,重点关注VLAN间通信、路由选择机制、安全策略控制等关键环节,并注意不同设备型号间的命令差异。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值