CF1285F Classical?

CF1285F Classical?

传送门

CodeForces

题解

一道比较神仙的题目吧.

你考虑枚举两个数(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;
}
原文地址:https://www.cnblogs.com/fexuile/p/12868976.html