洛谷 P6786「SWTR-6」GCDs & LCMs

由于现在还没有入到主题库里,暂时没有题号和题目链接

题目大意

给出一个长度为 n n n 的序列 a a a,你需要找出它的一个子序列 b b b(设 b b b 的长度为 m m m),并满足以下条件

  • 对于所有 ( 1 ≤ i ≤ m ) (1\le i \le m) (1im) b i b_i bi 要么是 b b b 中最大的元素,要么存在一个 b j > b i b_j>b_i bj>bi,满足 b i + b j + gcd ⁡ ( b i , b j ) = lcm ⁡ ( b i , b j ) b_i+b_j+\gcd(b_i,b_j)=\operatorname{lcm}(b_i,b_j) bi+bj+gcd(bi,bj)=lcm(bi,bj)
  • ∑ i = 1 m b i \sum\limits_{i=1}^m b_i i=1mbi 尽可能大
    n ≤ 3 × 1 0 5 n\le 3 \times 10^5 n3×105
前置芝士

集合的交与并以及其符号

解题思路

首先,我们先将 b i + b j + gcd ⁡ ( b i , b j ) = lcm ⁡ ( b i , b j ) b_i+b_j+\gcd(b_i,b_j)=\operatorname{lcm}(b_i,b_j) bi+bj+gcd(bi,bj)=lcm(bi,bj) 化简
b i + b j + gcd ⁡ = lcm ⁡ gcd ⁡ × gcd ⁡ b_i+b_j+\gcd=\frac{\operatorname{lcm}}{\gcd} \times \gcd bi+bj+gcd=gcdlcm×gcd
b i + b j = ( lcm ⁡ gcd ⁡ − 1 ) × gcd ⁡ b_i+b_j=(\frac{\operatorname{lcm}}{\gcd}-1) \times \gcd bi+bj=(gcdlcm1)×gcd
b i gcd ⁡ + b j gcd ⁡ = ( lcm ⁡ gcd ⁡ − 1 ) \frac{b_i}{\gcd}+\frac{b_j}{\gcd}=(\frac{\operatorname{lcm}}{\gcd}-1) gcdbi+gcdbj=(gcdlcm1)
到了这,你应该会发现 b i gcd ⁡ × b j gcd ⁡ = b i ⋅ b j gcd ⁡ 2 = lcm ⁡ gcd ⁡ \frac{b_i}{\gcd}\times\frac{b_j}{\gcd}=\frac{b_i\cdot b_j}{\gcd^2}=\frac{\operatorname{lcm}}{\gcd} gcdbi×gcdbj=gcd2bibj=gcdlcm,原因是 lcm ⁡ ⋅ gcd ⁡ = b i ⋅ b j \operatorname{lcm} \cdot \gcd=b_i \cdot b_j lcmgcd=bibj
那么,我们就得到了 b i gcd ⁡ + b j gcd ⁡ = ( b i gcd ⁡ ⋅ b j gcd ⁡ − 1 ) \frac{b_i}{\gcd}+\frac{b_j}{\gcd}=(\frac{b_i}{\gcd} \cdot \frac{b_j}{\gcd}-1) gcdbi+gcdbj=(gcdbigcdbj1)
这时候我就赶紧跑去打了个表QwQ,发现只有 ( 2 , 3 ) (2,3) (2,3) 这个组合满足两数之和等于两数之积减一。也就是说,当且仅当 b i b j = 2 3 \frac{b_i}{b_j}=\frac{2}{3} bjbi=32 的时候,原式才成立。

由此,题目就被我们化成了这样: b i b_i bi 要么是 b b b 中最大的,要么存在一个 b j b_j bj,满足 b i b j = 2 3 \frac{b_i}{b_j}=\frac{2}{3} bjbi=32
剩下的就很简单了,直接计算最长链就好了

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int Maxn=300000+10;
map <int,int> c;
map <int,bool> vis;
int a[Maxn],n;
long long ans;
inline int read()
{
    
    
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
int main()
{
    
    
//	freopen("in.txt","r",stdin);
	n=read();
	for(int i=1;i<=n;++i)
	{
    
    
		a[i]=read();
		c[a[i]]++;
	}
	sort(a+1,a+1+n);
	for(int i=1;i<=n;++i)
	{
    
    
		if(vis[a[i]])continue;
		register int x=a[i];
		register long long tot=0;
		while(c[x])
		{
    
    
			tot+=(long long)c[x]*x;
			vis[x]=1;
			if(x & 1)break;
			x=(x>>1)*3;
		}
		ans=max(ans,tot);
	}
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Brian_Pan_/article/details/108172107