CF1285F Classical?
传送门
题解
一道比较神仙的题目吧.
你考虑枚举两个数(x,y),那么(lcm(x,y)=frac{xy}{gcd(x,y)})
我们枚举(g=gcd(x,y)),那么有(ans=max(ans,x*y) [gcd(x,y)=1])
所以可以直接枚举这个(g),然后只需要判断与它互质的数然后( ext{check})答案即可.
问题在于怎么优化这个过程?考虑如果存在一个(gcd (x,y)=1),那么对于(x)所有的(x<z<y)都不能产生贡献.
拿一个栈维护这个过程即可.
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define REP(a,b,c) for(int a=b;a<=c;a++)
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
typedef pair<int,int> pii;
#define mp make_pair
inline int gi()
{
int f=1,sum=0;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int N=100010;
int n,a[N],m,mu[N],cnt[N],top,stk[N];
vector<int>g[N];
int main()
{
n=gi();ll ans=0;
for(int i=1,x;i<=n;i++)x=gi(),m=max(m,x),ans=m,a[x]=1;
mu[1]=1;
for(int i=1;i<=m;i++)
for(int j=i+i;j<=m;j+=i)mu[j]-=mu[i];
for(int i=1;i<=m;i++)
for(int j=i;j<=m;j+=i)g[j].push_back(i),a[i]|=a[j];
for(int i=m;i;i--)
if(a[i])
{
int tot=0;
for(int j:g[i])tot+=mu[j]*cnt[j];
while(tot>0&&top)
{
int ret=tot;
for(int j:g[stk[top]])
{
cnt[j]--;
if(!(i%j))tot-=mu[j];
}
if(ret!=tot)ans=max(ans,1ll*i*stk[top]);
top--;
}
for(int j:g[i])cnt[j]++;
stk[++top]=i;
}
printf("%lld
",ans);
return 0;
}