CF1285F Classical?

数列$a_{1..n}$

$lcm(a,b)=\frac{a*b}{gcd(a,b)}$

枚举$gcd(a,b)<=\sqrt n$,构成$gcd$,$a_i/gcd=b_i$,变成了求$b_i$中乘积最大互质。

将b_i从大到小排序,设置一个栈$s$,遍历$b_i$,设当前遍历为$x$?

  • $ans=max(ans,xk(栈内与x互质的最大数)g)$
  • 贪心的发现比$k$小栈内的数都失去了机会。

如何找到$k$,可以通过找到栈内有多少与$k$互质的数。

一个数的因数个数$\log n$

复杂度$O(sqrt(n)nlog(n))$ ,实现:$600ms\leq 1000ms$

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
vector<int> d[N];
int prime[N], notprime[N], mu[N], cnt;
int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
}
void init()
{
for (int i = 1; i < N; i++)
for (int j = 1; j * j <= i; j++)
if (i % j == 0)
{
d[i].push_back(j);
if (j * j != i)
d[i].push_back(i / j);
}
mu[1] = 1;
for (int i = 2; i < N; i++)
{
if (!notprime[i])
{
prime[++cnt] = i;
mu[i] = -1;
}
for (int j = 1; j <= cnt && i * prime[j] < N; j++)
{
notprime[i * prime[j]] = 1;
if (i % prime[j])
{
mu[i * prime[j]] = mu[i] * (-1);
}
else
{
mu[i * prime[j]] = 0;
break;
}
}
}
}
bool cmp(int a, int b)
{
return a > b;
}
ll ans;
int n, v[N], a[N], dd[N], b[N];
int main()
{

scanf("%d", &n);
for (int i = 1; i <= n; i++)
{

scanf("%d", &a[i]);
v[a[i]]++;
}
sort(a + 1, a + 1 + n, cmp);
for (int i = 1; i < N; i++)
if (v[i] >= 2)
ans = max(1ll * i, ans);
init();
for (int g = 1; g <= sqrt(N); g++)
{
stack<int> s;
int num = 0;
for (int i = 1; i <= n; i++)
if (a[i] % g == 0)
b[++num] = a[i] / g;
if (num <= 1)
continue;
for (int i = 1; i <= num; i++)
{
//cout << g << " " << a[i] << endl;
int res = 0, x = b[i];
for (int t = 0; t < d[x].size(); t++)
res += dd[d[x][t]] * mu[d[x][t]];
//cout << res << endl;
while (res > 0 && !s.empty())
{
int y = s.top();
s.pop();
if (gcd(x, y) == 1)
{
ans = max(ans, 1ll * x * y * g);
res--;
}
for (int t = 0; t < d[y].size(); t++)
dd[d[y][t]]--;
}
s.push(x);
for (int t = 0; t < d[x].size(); t++)
dd[d[x][t]]++;
}
while (!s.empty())
{
int y = s.top();
s.pop();
for (int t = 0; t < d[y].size(); t++)
dd[d[y][t]]--;
}
}
printf("%lld\n", ans);
}