AtCoder Beginner Contest 136 E - Max GCD

Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 500 points

Problem Statement

We have a sequence of N integers: A1,A2,⋯,AN.

You can perform the following operation between 0 and K times (inclusive):

  • Choose two integers i and j such that i≠j, each between 1 and N (inclusive). Add 1 to Ai and −1 to Aj, possibly producing a negative element.

Compute the maximum possible positive integer that divides every element of A after the operations. Here a positive integer x divides an integer y if and only if there exists an integer z such that y=xz.

题意很简单: 对于给你的N的整数A1~AN 可以进行0~k次操作,从1~N中任取俩数,Ai和Aj(i!=j),Ai + 1 且 Aj - 1 , 最后使A1~AN的公因数最大

Constraints

  • 2≤N≤500
  • 1≤Ai≤10^6
  • 0≤K≤10^9
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

N K
A1 A2 ⋯⋯ AN−1 AN

Output

Print the maximum possible positive integer that divides every element of A after the operations.


Sample Input 1 

2 3
8 20

Sample Output 1 

7

77 will divide every element of AA if, for example, we perform the following operation:

  • Choose i=2,j=1. A becomes (7,21)(7,21).

We cannot reach the situation where 8 or greater integer divides every element of A.


Sample Input 2 

2 10
3 5

Sample Output 2 

8

Consider performing the following five operations:

  • Choose i=2,j=1. A becomes (2,6)(2,6).
  • Choose i=2,j=1. A becomes (1,7)(1,7).
  • Choose i=2,j=1. A becomes (0,8)(0,8).
  • Choose i=2,j=1. A becomes (−1,9)(−1,9).
  • Choose i=1,j=2. A becomes (0,8)(0,8).

Then, 0=8×0 and 8=8×1, so 88 divides every element of A. We cannot reach the situation where 9 or greater integer divides every element of A.


Sample Input 3 

4 5
10 1 2 22

Sample Output 3 

7

Sample Input 4 

8 7
1 7 5 6 8 2 6 5

Sample Output 4 

5

思路:

既然是A1~AN的所有数的因数,那么也是它们和sum的因数,所以枚举sum的所有因数,测试因数g,算出A1~AN对g的余数,并进行从小到大的排序,左边的数(即余数小的数)先减成g的倍数,右边的数(即余数大的数)对应加上减去的数,补成g的倍数

 至于说为什么这样一定成功,我还没想明白

接下来是某个大佬的代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=500+9;
int n;
int a[maxn],lmt,b[maxn];


bool check(int g){
    for(int i=1;i<=n;++i)b[i]=a[i]%g;
    sort(b+1,b+n+1);
    int tot=lmt,cost=0;
    int t=n;
    for(int i=1;i<=t;++i){
        tot-=b[i];
        if(tot<0)return false;
        cost+=b[i];
        //b[i]=0;
        while(cost>0){
            int d=g-b[t];//此时d就是b[t]距离g的倍数最近的距离,好好想下就明白了 
            if(d<=cost){
                //b[t]=0;
                cost-=d;
                --t;
            }else{
                b[t]+=cost;
                cost=0;
            }
        }
    }
    return true;
}

int solve(){
	int sum=0;
	for(int i=1;i<=n;++i)sum+=a[i];
	
	int qt=sqrt(sum);
	vector <int> d;// divisor
	for(int i=1;i<=qt;++i)
	if(sum%i==0){
		d.push_back(i);
		if(check(sum/i))return sum/i;
	}
	int tot=d.size();
	for(int i=tot-1;i>=0;--i){
		if(check(d[i]))return d[i];
	}
}

void init(){
	cin>>n>>lmt;
	for(int i=1;i<=n;++i)cin>>a[i];
}
int main(){
	init();
	cout<<solve()<<"\n";
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值