原题链接:https://www.luogu.com.cn/problem/CF632D
题意解读:找个最长子序列,使得其LCM<=m
解题思路:
LCM最大值为1000000,不妨枚举这个LCM,然后看有多个数是其约数,这样做时间复杂度为n*m。
换一个角度,从每个数出发,通过类似埃氏筛的方式将其倍数(<=m)进行标记+1,最终看被标记次数最多的数即可。
直接从每个数出发,复杂度可能过高,先最数据进行排序,只取<=m的部分,再去重,这样对于一个数的倍数的标记应该加上这个数的个数,
如此优化,整体复杂度可以做到n*logm
100分代码:
#include <bits/stdc++.h>
using namespace std;const int N = 1000005;int a[N], b[N], h[N], ans[N];
int n, m;int main()
{cin >> n >> m;for(int i = 1; i <= n; i++) cin >> a[i];for(int i = 1; i <= n; i++) {b[i] = a[i]; //b是a的拷贝if(b[i] <= m) h[b[i]]++; //h记录b中每个数出现的次数}sort(b + 1, b + n + 1);int bn = unique(b + 1, b + n + 1) - (b + 1); //对b排序,去重for(int i = 1; i <= bn; i++){for(int j = b[i]; j <= m; j += b[i]){ans[j] += h[b[i]];}}int lcm = 1, cnt = 0;for(int i = 1; i <= m; i++) {if(ans[i] > cnt){cnt = ans[i];lcm = i;}}cout << lcm << " " << cnt << endl;if(cnt > 0){for(int i = 1; i <= n; i++){if(lcm % a[i] == 0) cout << i << " ";}}return 0;
}