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;
}