#模型转换#[ARC126C] Maximize GCD

题目

\(n\) 个数,最多 \(k\) 次让所选择的数加一,求 \(n\) 个数的GCD的最大值

\(n,a_i\leq 3*10^5,k\leq 10^{18}\)


分析

设答案为 \(d\) ,也就是使这 \(n\) 个数尽量靠近 \(d\) 的倍数。

那也就是使

\[k\geq \sum_{i=1}^n\lceil\frac{a_i}{d}\rceil*d-a_i \]

也就是

\[\lfloor\frac{k+s}{d}\rfloor\geq \sum_{i=1}^n\lceil\frac{a_i}{d}\rceil \]

如果 \(\large d>\max\{a_i\}\) 那么 \(\large d_{max}=\lfloor\frac{k+s}{n}\rfloor\),所以如果 \(\large \lfloor\frac{k+s}{n}\rfloor>\max\{a_i\}\) 答案为 \(\large \lfloor\frac{k+s}{n}\rfloor\)

否则答案一定在 \(\max\{a_i\}\) 中,枚举答案对于向上取整直接枚举倍数即可,时间复杂度 \(O(\max\{a_i\}\log\max\{a_i\})\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
typedef long long lll;
lll n,m,s,ans,c[300011],sum,mx,x;
lll iut(){
	lll ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int main(){
	n=iut(),m=iut();
	for (int i=1;i<=n;++i)
		m+=(x=iut()),mx=mx>x?mx:x,++c[x];
	for (int i=mx;i;--i) c[i-1]+=c[i];
	if (m/n>mx) return !printf("%lld",m/n);
	for (int i=mx;i;--i){
		lll sum=0;
		for (int j=1;j<=mx;j+=i) sum+=c[j];
		if (m/sum>=i) return !printf("%d",i);
	}
	return 0;
}
posted @ 2021-11-03 22:07  lemondinosaur  阅读(58)  评论(0编辑  收藏  举报