ABC136 E - Max GCD 题解

题面

给定一个长度为 $N$ 的整数序列:$A_1, A_2, \ldots, A_n$。

您可以执行以下操作 $0 \sim K$ 次:

选择两个整数 $i$ 和 $j$,满足 $i \ne j$ 并且 $1 \le i, j \le N$。令 $A_i$ 加上 $1$,令 $A_j$ 减去 $1$,可能产生负的元素。

计算在执行完操作后,整除 $A$ 中每个元素的最大可能正整数。这里正整数 $x$ 整除整数 $y$ 当且仅当存在一个整数 $z$,使得 $y=xz$。

思路

容易发现\(n\)很小,且答案\(ans\)一定为序列的权值和的因子,又发现,无论经过多少次操作后,总和均不变。考虑枚举\(ans\),记录下每一个值在当前情况下的余数,排序后用双指针找需要把所以余数都归零的操作次数,是否大于k判合法性即可

code

点击查看代码
#include <bits/stdc++.h>
using namespace std;
int read() {
	int a=0,f=0;
	char c=getchar();
	for(; c<'0'||c>'9'; c=getchar())if(c=='-')f=1;
	for(; c>='0'&&c<='9'; c=getchar())a=a*10+c-'0';
	return f?-a:a;
}
const int N=5e2+10;
int n,sum=0,ans=0,k,kk;
int p[N],b[N];
int main() {
	n=read(),k=read(),kk=k;
	for(int i=1; i<=n; ++i) p[i]=read(),sum+=p[i];
//	cout<<sum<<endl;
	for(int i=1; i<=sum; ++i) {
//		cout<<"sy "<<i<<" "<<sum<<" "<<sum%i<<endl;
		if(sum%i!=0) continue;
		int x=sum/i;
//		cout<<"i: "<<i<<endl;
		k=kk;
		for(int j=1; j<=n; ++j) {
			b[j]=p[j]%i;
		}
		sort(b+1,b+1+n);
		bool flag=0;
		int kun=0,l=1,r=n;
//		cout<<"b: ";
//			for(int d=1; d<=n; ++d) {
//				cout<<b[d]<<" ";
//			}
//			cout<<endl;
		while(l<=r) {
//			cout<<"b: ";
//			for(int d=1; d<=n; ++d) {
//				cout<<b[d]<<" ";
//			}
//			cout<<endl;
			int fl=b[l],fr=b[r],gl=fl,gr=i-fr;
//			cout<<i<<" "<<l<<" "<<r<<" "<<gl<<" "<<gr<<" "<<k<<" "<<sum<<endl;
			if(b[l]==0) {
				l++;
				continue;
			}
			if(fl+fr==i) {
				k-=fl;
				if(k<0) {
					flag=1;
					break;
				}
				l++,r--;
				continue;
			}
			if(gl>gr) {
				k-=gr;
				b[l]-=gr;
				r--;
				if(k<0) {
					flag=1;
					break;
				}
				continue;
			}
			if(gl<gr) {
				k-=gl;
				b[r]+=gl;
				l++;
				if(k<0) {
					flag=1;
					break;
				}
				continue;
			}
		}
//		cout<<"i: "<<flag<<endl;
		if(!flag) {
			ans=max(ans,i);
		}
	}
	cout<<ans;
	return 0;
}
/*
8 7
1 7 5 6 8 2 6 5
*/


posted on 2023-02-02 16:19  赵恒猿  阅读(45)  评论(0)    收藏  举报