• CF632D Longest Subsequence


    D. Longest Subsequence
    time limit per test
     2 seconds
    memory limit per test
     256 megabytes
    input
     standard input
    output
     standard output

    You are given array a with n elements and the number m. Consider some subsequence of a and the value of least common multiple (LCM) of its elements. Denote LCM as l. Find any longest subsequence of a with the value l ≤ m.

    A subsequence of a is an array we can get by erasing some elements of a. It is allowed to erase zero or all elements.

    The LCM of an empty array equals 1.

    Input

    The first line contains two integers n and m (1 ≤ n, m ≤ 10^6) — the size of the array a and the parameter from the problem statement.

    The second line contains n integers ai (1 ≤ ai ≤ 10^9) — the elements of a.

    Output

    In the first line print two integers l and kmax (1 ≤ l ≤ m, 0 ≤ kmax ≤ n) — the value of LCM and the number of elements in optimal subsequence.

    In the second line print kmax integers — the positions of the elements from the optimal subsequence in the ascending order.

    Note that you can find and print any subsequence with the maximum length.

    Examples
    input
    7 8
    6 2 9 2 7 2 3
    
    output
    6 5
    1 2 4 6 7
    
    input
    6 4
    2 2 2 3 3 3
    
    output
    2 3
    1 2 3
    一句话题意:

    分析:对于一个数k,它的所有约数的lcm肯定不大于k,也就是说对于每一个[1,m]中的数,我们只需要求出它的约数是a中的数的个数就好了,难道又要用筛法或质因数分解吗?其实不必,我们可以想到一个O(nm)的做法:枚举[1,m]中的每一个数,然后看看a中有多少个数整除它,显然T掉,能不能改进一下呢?
    对于枚举的优化,要么是减少枚举层数,要么是减少对答案没有贡献的枚举,我们可以只用枚举整除数i的数,然后看看a中有没有这个数,这个操作可以用一个vis数组,只需要O(1)的时间查询。不过ai <= 10^9,我们似乎开不下这么大的vis数组,观察题目,发现m只有10^6,大于10^6的数我们可以不用考虑.
    其实相对于枚举约数,枚举倍数更容易,我们从一个数扩展,将它的倍数的计数器累加即可,其实两种方法都可以.
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const int maxn = 1000010;
    
    int num[maxn], cnt[maxn],tot,a[maxn],ans,id,vis[maxn];
    int n, m;
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
            int t;
            scanf("%d", &t);
            a[i] = t;
            if (t > m)
                continue;
            ++num[t];
        }
        for (int i = 1; i <= n; i++)
        {
            if (!vis[a[i]])
            for (int j = a[i]; j <= m; j += a[i])
                cnt[j] += num[a[i]];
            vis[a[i]] = 1;
        }
        for (int i = 1; i <= m; i++)
            if (cnt[i] > ans)
            {
                ans = cnt[i];
                id = i;
            }
        printf("%d %d
    ", id, ans);
        for (int i = 1; i <= n; i++)
            if (id % a[i] == 0)
                printf("%d ", i);
    
        return 0;
    }

  • 相关阅读:
    python常见错误
    接口自动化常用断言方法python
    Mysql2docx自动生成数据库说明文档
    常用的实用小工具
    移动App专项测试
    AndroidStudio 快捷键(最实用的20个)(转)
    Linux常用命令大全(非常全!!!)(转)
    Fiddler使用教程(转)
    Subversion Edge
    杂点
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7391207.html
Copyright © 2020-2023  润新知