[AtCoder Beginner Contest 136]Max GCD

https://atcoder.jp/contests/abc136/tasks/abc136_e
分数:2100
Time Limit: 2 sec
Memory Limit: 1024 MB

Problem Statement

We have a sequence of N N N integers: A 1 , A 2 , ⋯ , A N A_1,A_2,⋯,A_N A1,A2,,AN.

You can perform the following operation between 0 0 0 and K K K times (inclusive): Choose two integers i i i and j j j such that i i i j j j, each between 1 1 1 and N N N (inclusive). Add 1 1 1 to A i A_i Ai and − 1 −1 1 to A j A_j 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 x x divides an integer y y y if and only if there exists an integer z z z such that y = x z y=xz y=xz.
Constraints
2 ≤ N ≤ 500 2≤N≤500 2N500
1 ≤ A i ≤ 1 0 6 1≤A_i≤10^6 1Ai106
0 ≤ K ≤ 1 0 9 0≤K≤10^9 0K109
All values in input are integers.

Input

Input is given from Standard Input in the following format:

N N N K K K
A 1 , A 2 ⋯ A N − 1 , A N A_1, A_2 ⋯ A_{N−1} ,A_N A1,A2AN1,AN

Output

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

Sample Input

2 10
3 5

Sample Output

8

Consider performing the following five operations:

Choose i=2,j=1. A becomes (2,6).
Choose i=2,j=1. A becomes (1,7).
Choose i=2,j=1. A becomes (0,8).
Choose i=2,j=1. A becomes (−1,9)
.Choose i=1,j=2. A becomes (0,8)
Then, 0=8×0 and 8=8×1, so 8 divides every element of A. We cannot reach the situation where 9 or greater integer divides every element of A.

题意:
给定 n ( n &lt; = 500 ) n(n&lt;=500) n(n<=500)个数字 A 1 A_1 A1 A n A_n An还有最多操作次数 k k k
每次操作能够选出一对不同的 i i i j j j,让 A i A_i Ai加一,并让 A j A_j Aj减一
问最大的x,满足在 k k k次操作内,把所有 A i A_i Ai变为 k k k的倍数。

题解:
s u m = ∑ i = 1 n A i sum = \sum^n_{i=1} Ai sum=i=1nAi
因为我们的操作不会改变 s u m sum sum但是一堆 k k k的倍数之和依旧是 k k k的倍数
那么答案一定是 s u m sum sum的因数之一
那么考虑枚举 s u m sum sum的因数,对答案进行check
设答案为 x x x
我们讲 A i A_i Ai按照 A i A_i Ai m o d mod mod x x x从小到大排序
根据贪心,我们可以发现 A i A_i Ai m o d mod mod x x x比较小的是可以用减操作,比较大的用加操作。然后就可以头尾配对贪心取操作数了,最后判断操作数是否 &lt; = k &lt;=k <=k来判断解的合法性即可。

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
using namespace std;
int n,k,A[504],sum;
int det[504];
bool check(int x){
    if(sum%x!=0)return 0;
    for(int i=1;i<=n;i++)det[i]=A[i]%x;
    sort(det+1,det+n+1);
    int l=1,r=n;
    ll opc=0;
    while(l<=r){
        if(det[l]%x==0){
            ++l;continue;
        }
        if(det[r]%x==0){
            --r;continue;
        }
        int delta=min(det[l]%x,x-(det[r]%x));
        det[l]-=delta;
        det[r]+=delta;
        opc+=delta;
    }
    return (opc<=k);
}
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)scanf("%d",&A[i]);
    sum=0;
    for(int i=1;i<=n;i++)sum+=A[i];
    int ans=1;
    for(int k=sqrt(sum);k>=1;k--){
        if(check(k))ans=max(ans,k);
        if(check(sum/k))ans=max(ans,sum/k);
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值