CF264B Good Sequences (神奇的DP)

 

洛谷链接:

https://www.luogu.org/problemnew/show/CF264B

 

codeforces题号:    CF264B Good Sequences

 

这也是来自vjudge的一道好题。

刚开始看到的时候想到了LIS,但是因为n<=10^5,所以N^2的LIS就肯定行不通了(但是考场上实在想不出来暴力也是必须的)

然后我就又想到了LIS的nlog(n)优化,但是这里需要想一下,因为nlog(n)的LIS是使d[len]尽量的小,这样才可以往后接更多的,但是这里并非这个数字越小,往后可以接的数字越多,因为因子的个数是不存在单调性的,所以这个方法也否决了。

 

如果大家希望学习一下nlog(n)的LIS,可以参考这里:

 

https://www.cnblogs.com/PencilWang/p/5917717.html

 

然后我们可以套用LIS的一部分思想,我们在LIS中,F[i]表示以A[i]结尾的最长上升子序列,我们这里的F[i]就可以表示成到现在为止以i这因子为结尾可接上的最长的LIS的长度,那么显而易见,我们刚开始只需要预处理出所有数的所有因子,但是这里还有一个注意点,因为两个数即使互质,也有一个公因数1,所以1不能作为这个数的因子去记录。

然后就开始了我们的重点部分:

先O(n)扫这整一个数组,当扫到第i个数的时候,将之前预处理出来的所以i的因子都提取出来,并++f[因子],这样就可以算出i的每一个因子到现在为止可以接到的最长的LIS的长度。同时记录一下最大的f[因子],记为maxnow

然后再对应第i个数的因子再扫出来一遍,对应dp[因子]=maxnow,因为接下来的一个数只要和当前的这个数有一个因子(不能为1)相同,则这两个数就不是互质的,就可以接在这一个数字的后面,所以所有的f[当前这个数的因子]都等于maxnow。然后最后只需要从1到a[n]扫一遍就可以得出最长的子序列。

 这是我的AC代码:供大家参考。

#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
int n,maxx,anss;
vector<int>ans[200001];
int a[1000001];
int f[1000001];
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;++i){
        scanf("%d",&a[i]);
    }
    
    for (int i=1;i<=n;++i){
        for (int j=2;j<=round(sqrt(a[i]));++j)
        if (a[i]%j==0){
            ans[i].push_back(j);
            if (j*j!=a[i]) 
                ans[i].push_back(a[i]/j);
        }
        ans[i].push_back(a[i]);
    }
    for (int i=1;i<=n;++i){
        int nowmax=0;
        for (int j=0;j<=ans[i].size()-1;++j){
            ++f[ans[i][j]];
            if (f[ans[i][j]]>nowmax) nowmax=f[ans[i][j]];
         }
        for (int j=0;j<=ans[i].size()-1;++j)
            if (f[ans[i][j]]<nowmax) f[ans[i][j]]=nowmax;
    }
    
    for (int i=1;i<=100010;++i) 
        if (f[i]>anss) anss=f[i];
        
    printf("%d",anss);
    
}

 

转载于:https://www.cnblogs.com/Dilemma/p/9309827.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值