【BZOJ】4052: [Cerc2013]Magical GCD-复杂度分析

博客介绍了BZOJ 4052题目的解决方案,主要讨论了如何通过固定区间左端点并让右端点递增来分析gcd(l, r)的变化次数,指出最多变化次数为log次。因此,使用st表维护区间gcd,并采用二分查找优化方法,使得总复杂度达到O(nlog2val)。" 105780200,9087918,Docker部署实践:搭建并管理Harbor私有仓库,"['Docker', '容器服务', 'Harbor', '仓库管理', '企业级部署']

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

传送门:bzoj4052


题解

冷静分析一下求解所有情况的复杂度:

固定区间左端点 l l l r r r递增的过程中 g c d ( l , r ) gcd(l,r) gcd(l,r)最多变化 l o g log log次。

于是 s t st st表维护区间 g c d gcd gcd,二分变化右端点。

复杂度 O ( n log ⁡ 2 v a l ) O(n\log^2 val) O(nlog2val)


代码

#include<stdio.h>
#include<iostream>
#include<math.h>
using namespace std;
const int N=100005;
#define ll long long
int T,n,i,j,x,l,r,mid,Log[N];
ll ans,f[N<<1][20];
inline void read(ll &v){
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
ll gcd(ll a,ll b)
{
    if(b==0) return a;else return gcd(b,a%b);
}
ll solve(int l,int r)
{
    int x=Log[r-l+1];
    return gcd(f[l][x],f[r-(1<<x)+1][x]);
}
int main()
{
    scanf("%d",&T);
    for(i=1;i<=100000;i++)
        Log[i]=log2(i);
    while(T--)
    {
        scanf("%d",&n);
        ans=0;
        for(i=1;i<=n;i++) read(f[i][0]);
        for(j=1;(1<<j)<=n;j++)
         for(i=1;i<=n;i++)
         f[i][j]=gcd(f[i][j-1],f[i+(1<<j-1)][j-1]);
        for(i=1;i<=n;i++)
        {
            x=i;
            while(x<=n)
            {
                l=x;r=n;
                ll s=solve(i,x);
                while(l<=r)
                {
                    mid=(l+r)>>1;
                    if(s==solve(i,mid)) l=mid+1;else r=mid-1;
                }
                ans=max(ans,solve(i,r)*(r-i+1));
                x=l;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值