zoukankan      html  css  js  c++  java
  • 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;
    }

  • 相关阅读:
    常用的公共 DNS 服务器 IP 地址
    组网参考资料
    华为交换机配置telnet、SSH
    华为三层交换+双链路出口
    ACL流策略
    MacBook苹果电脑绕过BootCamp安装Win7双系统
    nslookup
    熟悉Linux操作系统的命令接口、图形接口和程序接口
    “发现一个错误”——laravel开发
    document.forms用法示例介绍
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7391207.html
Copyright © 2011-2022 走看看