link
https://ac.nowcoder.com/acm/contest/6112/C
description:
有个n个数 希望求一个x 使得每个数 +x 的gcd 值最大 ,求出gcd值 和 最小的x
solution:
gcd的性质: gcd(x,y) = gcd(x,y - x) 三个数也是一样
从这个式子可以看出所有数+x之后 他们之间的差值不变 并且 gcd的值也不会变
所以求出他们的差分数组 将差分数组gcd就是最大的gcd值
求的x 就是要在数组中一个最小的数 使得它变成gcd的倍数 对于每个数 如果本身就可以被整除 答案就是0
否则 分成负数和正数 两种情况 处理%gcd的值即可
code:
#include <bits/stdc++.h> using namespace std; #define LL long long const int N = 1e6 + 50; LL a[N]; vector <LL> v; int main(){ int n;scanf("%d",&n); for(int i = 1;i <= n;i ++){ scanf("%lld",&a[i]); } sort(a + 1,a + 1 + n); for(int i = 2;i <= n;i ++){//求差分数组 v.push_back(a[i] - a[i - 1]); } LL gcd = -1; for(int i = 0;i < v.size(); i ++){//求最终的gcd值 复杂度n + logai if(gcd == -1){ gcd = v[i]; }else{ gcd = __gcd(gcd,v[i]); } } LL res = (LL)1e18;// 最大值 for(int i = 1;i <= n;i ++){ if(a[i] % gcd == 0){ res = 0; }else{ LL t; if(a[i] < 0){ t = - (a[i] % gcd); }else{ t = gcd - (a[i] % gcd); } res = min(res,t); } } printf("%lld %lld\n",gcd,res); return 0; }