[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 integers: A 1 , A 2 , , A N A_1,A_2,⋯,A_N .

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

Input

Input is given from Standard Input in the following format:

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

Output

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

Sample Input

扫描二维码关注公众号,回复: 8747308 查看本文章
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 < = 500 ) n(n<=500) 个数字 A 1 A_1 A n A_n 还有最多操作次数 k k
每次操作能够选出一对不同的 i i j j ,让 A i A_i 加一,并让 A j A_j 减一
问最大的x,满足在 k k 次操作内,把所有 A i A_i 变为 k k 的倍数。

题解:
s u m = i = 1 n A i sum = \sum^n_{i=1} Ai
因为我们的操作不会改变 s u m sum 但是一堆 k k 的倍数之和依旧是 k k 的倍数
那么答案一定是 s u m sum 的因数之一
那么考虑枚举 s u m sum 的因数,对答案进行check
设答案为 x x
我们讲 A i A_i 按照 A i A_i m o d mod x x 从小到大排序
根据贪心,我们可以发现 A i A_i m o d mod x x 比较小的是可以用减操作,比较大的用加操作。然后就可以头尾配对贪心取操作数了,最后判断操作数是否 < = 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;
}
发布了302 篇原创文章 · 获赞 19 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/dxyinme/article/details/98526235