#模型转换#[ARC126C] Maximize GCD

题目

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

(n,a_ileq 3*10^5,kleq 10^{18})


分析

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

那也就是使

[kgeq sum_{i=1}^nlceilfrac{a_i}{d} ceil*d-a_i ]

也就是

[lfloorfrac{k+s}{d} floorgeq sum_{i=1}^nlceilfrac{a_i}{d} ceil ]

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

否则答案一定在 (max{a_i}) 中,枚举答案对于向上取整直接枚举倍数即可,时间复杂度 (O(max{a_i}logmax{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;
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/15505979.html