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\n", id, ans);
    for (int i = 1; i <= n; i++)
        if (id % a[i] == 0)
            printf("%d ", i);

    return 0;
}

 


posted @ 2017-08-18 18:30  zbtrs  阅读(822)  评论(0编辑  收藏  举报