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;
    }

  • 相关阅读:
    Java扫描二维码进行会议签到思路
    Cognos11中通过URL传参访问动态Report
    MySQL数据复制到其他主机时报错
    ESXI部署OVF模板提示用户已取消操作处理方法
    Esxi 6.0虚拟机迁移Linux遇到网络配置错误
    数据库迁移工具Navicat Premium之OracleToMysql
    Cognos11中Dashboard和HTML页面的简单集成
    Cognos11只需简单几步创建你的Dashboard
    云服务器 ECS Linux Ubuntu 主机修改主机名
    gitlab webhook报500
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7391207.html
Copyright © 2011-2022 走看看