CF1285F Classical?
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\),然后只需要判断与它互质的数然后\(\text{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\n",ans);
return 0;
}