P6786 「SWTR-6」GCDs & LCMs

P6786 「SWTR-6」GCDs & LCMs

题目大意

给一个长度为\(n\)序列\(a\),从\(a\)中选出一些数,构成长度为\(m\)序列\(b\)
且序列\(b\)满足,对于任意的\(1\leq i \leq m\),要么\(b_i\)\(b\)中的最大值,要么存在\(1 \leq j \leq m\),使得\(b_j>b_i\text{且}b_i+b_j+gcd(b_i,b_j)=lcm(b_i,b_j)\)

求序列\(b\)所有元素之和的最大值

分析

  1. 第一次错误的尝试将

\[lcm(b_i,b_j)=\frac{b_ib_j}{gcd(b_i,b_j)} \]

然后,然后就没有然后嘞,因为发现我根本没法处理\(\frac{1}{gcd(b_i,b_j)}\)

  1. 正确思路
    \(gcd(b_i,b_j)=x\),则\(b_i=ax,b_j=bx\)

\[ax+bx+x=abx \]

\[ax+bx+x-abx=0 \]

\[a+b-ab+1=0 \]

\[a+b-ab-1=-2 \]

\[(a-1)-b(a-1)=-2 \]

\[(a-1)(1-b)=-2 \]

\[(a-1)(b-1)=2 \]

\[\because a,b\text{为整数} \]

\[\therefore a=2,b=3 \text{ or } a=3,b=2 \]

不妨令\(a=2,b=3\)
\(\because 2x<3x\)
所以其实就是找到一个集合,满足要么\(b_i=b_max\),要么\(\frac{2}{3}b_i\)存在

要从序列\(a\)中找出最大的一个集合,很明显,\(DP\),map优化\(DP\)

  1. \(a\)排序
  2. \(a\)去重,并记录重复的个数。
  3. \(DP\)+map

复杂度\(O(n log_2 n)\)

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;

struct node { int x,s; }p[300010];
int n,m;
int a[300010],f[300010];
int ans=0;
map<int,int> q;
signed main()
{
	cin >> n;
	for (int i=1;i<=n;i++) cin >> a[i];
	sort(a+1,a+n+1);
	for (int i=1;i<=n;i++)
	{
		if (a[i]!=a[i-1]) m++,p[m].x=a[i],p[m].s=1;
		else p[m].s++;
	}
	for (int i=1;i<=m;i++)
	{
//		printf("%lld\n",p[i].x);
		if (p[i].x%3==0) f[i]=p[i].x*p[i].s+q[p[i].x/3];
		else f[i]=p[i].x*p[i].s;
		if (p[i].x%2==0) q[p[i].x/2]=f[i];
		ans=max(ans,f[i]);
	}
	printf("%lld",ans);
}
posted @ 2021-11-16 22:47  WBWYX  阅读(56)  评论(0)    收藏  举报