题目链接
题目解法
考虑枚举最大公因数
d
d
d
从大到小枚举是
d
d
d 的倍数
x
x
x,考虑如果有
(
x
,
z
)
=
d
(x,z)=d
(x,z)=d,那么
x
<
y
<
z
x<y<z
x<y<z 的所有
y
y
y 都是无意义的
考虑把之前枚举的数的倍数
d
d
d 放入栈中维护,栈顶小,栈底大,如果栈中仍有与
x
x
x 互质的数,那么就弹出栈头
考虑计算栈中与
x
x
x 互质的数的个数,这个用莫反可以轻松求到,为
∑
d
∣
i
μ
(
d
)
∗
s
u
m
d
\sum_{d|i}\mu(d)*sum_d
∑d∣iμ(d)∗sumd
其中
s
u
m
d
sum_d
sumd 为栈中为
d
d
d 的个数的数
这样可以用
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n) 求解
考虑对于 x , y x,y x,y, l c m ( x , y ) = l c m ( x , z ) , z = y ( x , y ) lcm(x,y)=lcm(x,z)\;,z=\frac{y}{(x,y)} lcm(x,y)=lcm(x,z),z=(x,y)y,这里 x , z x,z x,z 是互质的,例如 [ 4 , 6 ] = [ 4 , 3 ] [4,6]=[4,3] [4,6]=[4,3],于是可以把 n n n 的约数都放入集合中,只需要对于 d = 1 d=1 d=1 的情况做一遍上述操作即可,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N(100100),MX(100000);
int n,ans,a[N],cnt[N],sum[N],mu[N];
vector<int> g[N];
int stk[N],top;
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
int count(int x){//计算与x互质的数的个数
int res=0;
for(int i=0;i<g[x].size();i++) res+=mu[g[x][i]]*sum[g[x][i]];
return res;
}
void add(int x,int val){
for(int i=0;i<g[x].size();i++) sum[g[x][i]]+=val;
}
signed main(){
n=read();
for(int i=1;i<=MX;i++) mu[i]=1;
for(int d=1;d<=MX;d++){
for(int i=d;i<=MX;i+=d) g[i].push_back(d);
if(d==1) mu[d]=1;
else if((d/g[d][1])%g[d][1]==0) mu[d]=0;
else mu[d]=-mu[d/g[d][1]];
}
for(int i=1;i<=n;i++){
a[i]=read();
for(int j=0;j<g[a[i]].size();j++) cnt[g[a[i]][j]]++;
}
for(int i=MX;i;i--){
if(!cnt[i]) continue;
if(cnt[i]>1) ans=max(ans,i);
int pr=count(i);
while(pr){
if(__gcd(stk[top],i)==1) ans=max(ans,i*stk[top]),pr--;
add(stk[top--],-1);
}
stk[++top]=i,add(i,1);
}
printf("%lld",ans);
return 0;
}