D. Longest Subsequence(数论 + 暴力)

136 阅读1分钟

题目

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.

中文翻译

给你一个数组a随着n元素和数量m。考虑一些后续的a以及其元素的最小公倍数(LCM)的值。将LCM表示为l。找出任何最长的子序列a有了价值l ≤ m. 一连串的a是一个数组,我们可以通过删除a。允许擦除零个或所有元素。 空数组的LCM等于1.

输入

The first line contains two integers n and m (1 ≤ n, m ≤ 106) — the size of the array a and the parameter from the problem statement. The second line contains n integers ai (1 ≤ ai ≤ 109) — the elements of a.

中文翻译

第一行包含两个整数nm (1 ≤n, m≤ 106)—数组的大小a以及问题陈述中的参数。 第二行包含n整数a**i (1 ≤a**i≤ 109)—的元素a.

解法

题目的意思就是给我们一个数组让我们找出最长的子序列并且这个序列满足所有数的lcm<=m
首先我们知道一个数的lcm是肯定大于等于他本身的所以我们开个桶数组cnt去存储小于m的数字出现的个数
对于lcm我们用数组dp去表示对于dp[j] = cnt[i]\sum cnt[i](i <= j &&j % i == 0) 然后我们遍历一遍就行了然后输出我们的答案

Code

const int N = 1e6 + 10;
int dp[N], cnt[N];
int a[N];
void solve()
{
    int n, m; cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (a[i] <= m) cnt[a[i]] ++;
    }
    for (int i = m; i >= 1; i--)
        for (int j = i; j <= m; j += i)
            dp[j] += cnt[i];
    ll lcm = -1, mx = -1;
    for (int i = 1; i <= m; i++) {
        if (dp[i] > mx) {
            lcm = i;
            mx = dp[i];
        }
    }
    cout << lcm << ' ' << mx << endl;
    for (int i = 1; i <= n; i++) if (lcm % a[i] == 0) cout << i << ' ';
}