CF1285F Classical?

题意

给定 n n n 个正整数,求两两 lcm \text{lcm} lcm 的最大值。
所有输入在 [ 1 , 1 0 5 ] [1,10^5] [1,105]范围内。

分析

首先枚举 gcd ⁡ = g \gcd = g gcd=g,那么将数组中 g g g 的倍数都拿出来。
问题转化为,在数组中找两个互质的数,使他们的积尽量大。
我们将这些数从大到小枚举,那么枚举到一个数 x x x 时,在已经枚举到的数中,如果有 x , y x,y x,y 互质,那么对于所有 z ∈ [ x , y ] z\in[x,y] z[x,y] 的数,都不可能形成最终答案。所以可以维护一个栈,对于当前 x x x,如果存在 y y y x x x 互质,就弹掉 x x x y y y 之间的数。
那怎么判断数组中是否有与 x x x 互质的数?
c n t d cnt_d cntd 表示已经枚举的值中 d d d 的倍数的个数, t o t tot tot 表示与 x x x 互质的数的个数。那么由容斥原理, t o t = ∑ d ∣ x μ ( d ) × c n t d tot=\sum\limits_{d|x}\mu(d)\times cnt_d tot=dxμ(d)×cntd
然后每次入栈和弹栈,都用 σ 0 ( x ) \sigma_0(x) σ0(x) x x x 的约数个数) 的时间来更新 c n t cnt cnt 数组。
总复杂度是 O ( ∑ i = 1 n σ 0 ( i ) 2 ) O(\sum\limits_{i=1}^{n}\sigma_0(i)^2) O(i=1nσ0(i)2) 的,大概是 O ( n l o g 2 V ) O(nlog^2V) O(nlog2V)
因为每个数作为倍数都入过 σ 0 ( x ) \sigma_0(x) σ0(x) 次栈,每次入栈都要用 σ 0 ( x ) \sigma_0(x) σ0(x) 来更新 c n t cnt cnt 数组。

代码如下

#include <bits/stdc++.h>
#define N 100005
#define LL long long
using namespace std;
vector<int> d[N];
int mu[N], v[N], q[N], p[N], x[N], cnt[N], tot, y, maxn = N - 5;
LL t, z = 1;
int get(int x){
	int i, ans = 0;
	for(i = 0; i < d[x].size(); i++) ans += mu[d[x][i]] * cnt[d[x][i]];
	return ans;
}
void update(int x, int v){
	int i;
	for(i = 0; i < d[x].size(); i++) cnt[d[x][i]] += v;
}
int main(){
	int i, j, n, m, c;
	LL ans = 0;
	mu[1] = 1;
	for(i = 2; i <= maxn; i++){
		if(!x[i]) x[i] = p[++tot] = i, mu[i] = -1;
		for(j = 1; j <= tot; j++){
			t = z * i * p[j];
			if(t > maxn) break;
			x[t] = p[j];
			if(i % p[j] == 0) break;
			mu[t] = -mu[i];
		}
	}
	for(i = 1; i <= maxn; i++)
		for(j = 1; j <= maxn / i; j++) d[i * j].push_back(i);
	scanf("%d", &n);
	for(i = 1; i <= n; i++){
		scanf("%d", &j);
		v[j] = 1;
		ans = max(ans, z * j);
	}
	for(i = 1; i <= maxn; i++){
		for(j = maxn / i; j >= 1; j--){
			if(!v[i * j]) continue;
			c = get(j);
			while(c){
				if(__gcd(q[y], j) == 1){
					ans = max(ans, z * i * j * q[y]);
					c--;
				}
				update(q[y], -1);
				y--;
			}
			q[++y] = j;
			update(j, 1);
		}
		while(y > 0) update(q[y], -1), y--;
	}
	printf("%lld", ans);
	return 0;
}
经典网络是指在计算机科学领域中,早期应用广泛的网络结构类型。它指的是在互联网出现之前使用的传统网络结构。经典网络通常基于分层结构设计,由若干个网络层组成,每一层负责特定的功能。 在经典网络中,最常见的是OSI模型(开放系统互联模型)和TCP/IP模型(传输控制协议/互联网协议)这两种标准化网络模型。OSI模型被广泛接受并应用于网络协议的设计和实现,它将网络通信分为七个层次,包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。TCP/IP模型则将网络通信分为四个层次,包括网络接口层、网络层、传输层和应用层。 经典网络架构为数据传输提供了良好的结构和框架。例如,经典网络中的分层结构能够将不同的功能分配给不同的层次,提高了网络的可维护性和可扩展性。每个层次都有确定的功能和责任,使得网络的开发和管理更加简化。 然而,随着互联网的发展和技术的进步,经典网络逐渐被更为高级和复杂的网络架构所取代,如软件定义网络(SDN)和云计算等。这些新兴的网络架构更加灵活和可扩展,能够更好地适应现代应用的需求。 综上所述,经典网络是指互联网出现之前使用的传统网络架构类型,具有分层结构和规范化的网络模型。尽管在现代网络发展中逐渐被取代,但经典网络的设计思想和基本原理仍然对我们理解和构建网络系统有着重要的意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值