Codeforces.566F.Clique in the Divisibility Graph(DP)

博客围绕给定集合S,集合中两点有边的条件是元素间存在整除关系,要求找出满足任意两点间都有连边的最大子集S'。提出从小到大选取元素,可采用DP方法,每次更新其倍数,但复杂度可能被卡到O(n^2)。

题目链接

\(Description\)

给定集合\(S=\{a_1,a_2,\ldots,a_n\}\),集合中两点之间有边当且仅当\(a_i|a_j\)\(a_j|a_i\)
\(S\)最大的一个子集\(S'\),并满足\(S'\)中任意两点间都有连边(\(S'\)中只有1个点也是合法的)。
\(n,a_i\leq 10^6\)\(a_i\)互不相同。

\(Solution\)

从小到大选(已经排好序),如果选了\(a_i\),则下一个数一定是\(a_i\)的倍数,下下个数一定是下个数和这个数的倍数。。
容易想到DP,每次更新其倍数即可。

复杂度。。好像不是\(O(n\ln n)\)吧?哦,看漏了个\(a_i\)互不相同。。
\(a_i\)可相同就有趣了。
算了。。怎么着都能被卡到\(O(n^2)\)。。

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=1e6+5;

int n,A[N],f[N];

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}

int main()
{
    n=read(); int mx=0, ans=1;
    for(int i=1; i<=n; ++i) mx=std::max(mx,A[i]=read());
    for(int i=1; i<=n; ++i)
    {
        int a=A[i], v=++f[a];
        ans=std::max(ans,v);
        for(int j=a<<1; j<=mx; j+=a) f[j]=std::max(f[j],v);
    }
    printf("%d\n",ans);

    return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/9556560.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值