洛谷: CF632D Longest Subsequence-普及+/提高
题目描述
给定有 nnn 个元素的数组 aaa 和数字 mmm。记 LCM 为 lll 。找出使 l≤ml \le ml≤m 的 aaa 的最长子序列。
定义 aaa 的子序列为通过删除 aaa 中的一些元素得到的数组。允许删除 000 个元素或所有元素。
空数组的 LCM 等于 111。
输入格式
第一行包含两个整数 nnn 和 mmm ( $ 1 \le n,m \le 10^{6} $ ) — 数组 aaa 的大小和题目描述中的参数。
第二行包含 n 个整数 $ a_{i} $ ( $ 1 \le a_{i} \le 10^{9} $ ) — aaa 的元素。
输出格式
第一行打印两个整数 $ l $ 和 $ k_{\max} $ ( $ 1 \le l \le m,0 \le k_{\max} \le n $ ) — LCM 的值和最优子序列中的元素数量。
第二行打印 $ k_{\max} $ 个整数 — 按升序排序输出元素。
请注意,您可以找到并打印任何具有最大长度的子序列。
输入输出样例 #1
输入 #1
7 8
6 2 9 2 7 2 3
输出 #1
6 5
1 2 4 6 7
输入输出样例 #2
输入 #2
6 4
2 2 2 3 3 3
输出 #2
2 3
1 2 3
solution
代码
#include "cstring"
#include "string"
#include "algorithm"
#include "iostream"
#include "vector"
#include "unordered_set"
#include "unordered_map"
#include "bitset"
#include "queue"
#include "set"using namespace std;/** CF632D Longest Subsequence* 题目大意:n 个数, lcm <= m 的最长子序列 (n,m <= 1e6)* 1 统计 [1, m] 每个数出现的次数 c[i]* 2 仿照埃筛用 1 中出现的 i 标记它的倍数, f[i*j] += c[i]* 3 统计并输出 f 的最大值和最大值 index, 输出 index 的约数*/const int N = 1e6 + 5, M = 2e6, INF = 1e9, MOD = 0;
typedef long long ll;int n, m, a[N], c[N], f[N];int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) {scanf("%d", a + i);if (a[i] <= m) c[a[i]]++;}for (int i = 1; i <= m; i++) {if (c[i]) {for (int j = 1; j * i <= m; j++) {f[i * j] += c[i];}}}int ans = 0, k = 1;for (int i = 1; i <= m; i++)if (f[i] > ans) ans = f[i], k = i;printf("%d %d\n", k, ans);for (int i = 1; i <= n; i++) {if (k % a[i] == 0) printf("%d ", i);}return 0;
}