D - Longest Subsequence CodeForces - 632D

http://codeforces.com/problemset/problem/632/D

题意:给一段序列和一个正整数m,求这段序列的一个满足条件的最长子序列,条件是这个子序列的最小公倍数小于等于m

第一想法就是暴力,从m枚举到1,对每个当前枚举的值暴力给定序列里有几个是他的因子,然后类似素筛将他的因子全都标记掉,遇到标记的值直接跳过,结果t了,复杂度也不是很好计算,后来想了一些优化也是不可行的,这个方法应该是不可行的

后来想到把这个想法反过来,因为找因子的复杂度会高一写,不如开一个大小为m的数组num【i】,记录每个数 i 在序列里因子的个数,通过序列里的每个数,把他的所有小于m的倍数对应的num值++,最后扫一遍,求出num值最大的那个数即可

复杂度为:m+m/2+m/3+...+m/m   (据说叫调和级数)

#include<bits/stdc++.h>
using namespace std;
int book[1000005],book2[1000005];
int a[1000005];
vector <int> ans;
vector <int> num[1000005];
int cmp(int u,int v)
{
    return u<v;
}
int main()
{
    int n,m,i,j,maxx=0,anss=1;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(a[i]<=m)
        {
            num[a[i]].push_back(i);
            book2[a[i]]++;
        }
    }
    for(i=1;i<=m;i++)
    {
        if(book2[i])
        for(j=i;j<=m;j+=i)
        {
            book[j]+=book2[i];
        }
    }
    for(i=1;i<=m;i++)
    {
        if(book[i]>book[anss])
            anss=i;
    }
    for(i=1;i<=anss;i++)
    {
        if(anss%i==0)
        {
            for(j=0;j<num[i].size();j++)
            {
                ans.push_back(num[i][j]);
            }
        }
    }
    sort(ans.begin(),ans.end(),cmp);
    cout<<anss<<" "<<book[anss]<<endl;
    for(i=0;i<ans.size();i++)
        printf("%d ",ans[i]);
    cout<<endl;
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值