zoukankan      html  css  js  c++  java
  • CF1285F Classical?

    Description

    给定 ({a_n}),求 (max{lcm(a_i,a_j)})

    Solution

    一个显然的想法是枚举 gcd,然后求去掉 gcd 后互质的两个数的乘积最大值。一个显然的性质是如果 (x)(y) 互质,那么对任意 (y'leq y) 都不会和 (x'leq x) 来更新答案。维护一个栈,从大到小枚举 (x),找到最大的与 (x) 互质的 (y),然后把栈里面所有 (y'leq y) 都弹掉。

    如何找到最大的与 (x) 互质的数?实际上我们只需要知道栈里面存不存在与 (x) 互质的数。如果存在,那么就一直弹栈,因为迟早都要删掉。直到没有互质的了,最后一个被弹掉的就是要找的数。与 (x) 互质的数的个数为(其中 (c_i) 表示 (i) 的个数)

    [sum c_i [gcd(i,x)=1]=sum c_isum_{d|i,d|x} mu(d)=sum_{d|x} mu(d)sum_{d|i}c_i ]

    所以只需要时刻维护 (w_d) 表示 (d) 的倍数的个数。具体而言,预处理出每个数的约数,和 (mu),弹栈和入栈的时候更新就可以了。

    复杂度 (O(sum_{d=1}^{|V|} frac{|V|}{d}|V|^{frac{1}{3}})=O(|V|^{frac{4}{3}}log |V|))

    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    typedef long long ll;
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    const int N=1e5+7;
    
    bool mk[N];
    int n,a[N],cnt=0,p[N],w[N],sta[N],top=0,c[N],mu[N];
    vector<int> D[N];
    
    int gcd(int x,int y){
        return y? gcd(y,x%y):x;
    }
    
    int main(){
        n=read(); int rg=0;
        for(int i=1,x;i<=n;i++)
            rg=max(rg,x=read()),c[x]++;
        ll ans=0; mu[1]=1;
        for(int i=2;i<=rg;i++){
            if(!mk[i]){p[++cnt]=i,mu[i]=-1;}
            for(int j=1;j<=cnt&&p[j]*i<=rg;j++){
                mk[p[j]*i]=1;
                if(i%p[j]==0) break;
                mu[i*p[j]]=-mu[i];
            }
        }
        for(int i=1;i<=rg;i++)
            for(int j=i;j<=rg;j+=i)
                D[j].push_back(i);
        for(int d=1;d<=rg;d++){
            n=0;
            for(int i=d;i<=rg;i+=d)
                for(int j=1;j<=c[i];j++) a[++n]=i/d;
            for(int i=n;i;i--){
                int y=0,s=0;
                for(int j=0;j<D[a[i]].size();j++){
                    int x=D[a[i]][j];
                    s+=w[x]*mu[x];
                }
                while(s){
                    y=sta[top--];
                    if(gcd(y,a[i])==1) s--;
                    for(int j=0;j<D[y].size();j++)
                        w[D[y][j]]--;
                }
                if(y) ans=max(ans,1ll*y*a[i]*d);
                sta[++top]=a[i];
                for(int j=0;j<D[a[i]].size();j++)
                    w[D[a[i]][j]]++;
            }
            while(top){
                int y=sta[top--];
                for(int j=0;j<D[y].size();j++)
                    w[D[y][j]]--;
            }
        }
        printf("%lld",ans);
    }
    
  • 相关阅读:
    动态规划之背包问题
    Python中import导入上一级目录模块及循环import问题的解决
    Anaconda介绍、安装及使用教程
    负载均衡基础知识
    TCP和UDP的区别(转)
    microsoft visual c++ 14.0 is required问题解决办法
    python使用requests时报错requests.exceptions.SSLError: HTTPSConnectionPool
    解决Anaconda无法更新的问题
    彻底的理解TCP协议的三次握手和四次分手
    android调试工具 adb命令学习
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15171848.html
Copyright © 2011-2022 走看看