思路:贪心。这个题目首先可以通过自己的模拟,然后得出基本的规律。我们看,每个数都加上一个x的话,其实他们之间的差值是不变的。所以,我们可以考虑它的ans是否与他们的差值有关,然后自己可以通过模拟得出,这确实有关。我们也可以利用差分的知识得出结论,最终的答案就是在这些数的所有的差值之间找出一个最大的gcd。举个栗子,对于a[i]和a[j],我们假设gcd为a[i]和a[j]的最大公因子,a[i]%x==0,a[j]%x==0,那么(a[i]-a[j])%x==0,那么,既然a[i],a[j]都会改变,那么我们就不通过这些数来求,我们就通过他们的差值来求,那么该gcd就是这些差值之间的最大公因子,那么如何使得我们的gcd是最大的呢?显然,我们要求出多有的数之间的差值,然后再从中间找出最大的gcd。
但是,现在又面临一个问题就是我们的数据是1e6的,如果把每两项之间的差值求出来,时间肯定过不了,怎么办呢?
我们发现,对于我们只要先将所有的数进行非降次排序,然后利用后面一项的减前面的一项记录每一项差值,然后只要从这些差值之间找gcd就行了。我们可以发现,比如我们的a[1],a[2],a[3],a[4],a[5]...a[n],这些都已经排好序了,我们也记录了相邻两项之间的差值,都放在b数组里面。如果我们记录a[n]-a[1]的差值为m的话,其实是没有必要的,因为我们一定可以在b数组里面找到两个数x,y,他们的和或者差值就是m(这个要慢慢理解,这才是本题的核心)。所以,其实b数组里面的数就是最基本的元素了所有的差值都是这些元素进行加减变换得到的。
然后,接下来就是如何来求相邻两项之间的差值了,先排序,然后相邻两项相减,得到的差值放到b数组里面,但是要注意的是不要把0放进去,因为,你后面还要求这些里面的最大的gcd,0完全没有贡献对于这个。然后,我们找到b数组里面最小的那个数min,我们可以知道gcd<=min,然后用一个for循环,从大到小进行判断,一旦找到可以整除所有差值的,立马退出循环,最后求x即可。
代码如下:
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll a[1000010],b[1000010]; int k=0; bool judge(ll x){ for(int i=0;i<k;i++){ if(b[i]%x!=0) return false; } return true; } int main(){ std::ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n); for(int i=1;i<n;i++){ ll temp=a[i]-a[i-1]; if(temp>0) b[k++]=temp; //不要把0放进b数组 } sort(b,b+k); //对b排序,找出最小的b的元素 ll gcd=b[0]; while(1){ //从大到小进行判断 if(judge(gcd)) break; gcd--; } ll x=abs(a[0])%gcd; //随便找一个a数组中的元素,但要不为0,然后对最大gcd求模即可 cout<<gcd<<" "<<x<<endl; return 0; }