- 通过计算数组中两数的差值的g(最大公约数)来求数组中所有数加k后的公约数,因为数组中每个数加非负整数k不改变相邻两数的差值。设g为a,b的最大公约数,则a = g*m,b = g*n,a-b=g(m-n),显然g是a-b的公约数.
- 求公约数用欧几里得算法,迭代求出所有差值的最大公约数.
- k值计算:若存在k使得数组中所有数加k后的最大公约数为g,那么数组中的任意一个数arr[0](取第一个数)满足arr[0]+k为g的倍数。arr[0]与g取模,得到r为arr[0]模g的余数,k就等于g-r,为了确保最小k,k =(g-r)modg.
#include <stdio.h>
#include <math.h>
int gcd(int a, int b);
int main() {
int n;
scanf("%d", &n);
int arr[n];
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
//计算差值的最大公约数
int g_max = 0;//存储最大公约数,初始化为0,gcd(0,x)=x;
for (int i = 1; i < n;i++) {
int diff = abs(arr[i] - arr[i - 1]); //相邻差值
g_max = gcd(g_max, diff);
}
//计算最小的非负k
int r = arr[0] % g_max; // 第一个数模g_max的余数
int min_k = (g_max - r) % g_max; // 保证k≥0且最小
//输出结果(最大GCD + 最小k)
printf("%d %d\n", g_max, min_k);
return 0;
}
int gcd(int a, int b) {
while (b != 0) { //当除数为0时退出
int temp = b;
b = a % b;
a = temp;
}
return a;//返回被除数
}