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\)所有元素之和的最大值
分析
- 第一次错误的尝试将
\[lcm(b_i,b_j)=\frac{b_ib_j}{gcd(b_i,b_j)}
\]
然后,然后就没有然后嘞,因为发现我根本没法处理\(\frac{1}{gcd(b_i,b_j)}\)
- 正确思路
设\(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\)
- 将\(a\)排序
- 将\(a\)去重,并记录重复的个数。
- \(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);
}
浙公网安备 33010602011771号