公因子(gcd性质)
思路:
g c d gcd gcd性质: g c d ( a , b ) = g c d ( a , b − a ) gcd(a,b)=gcd(a,b-a) gcd(a,b)=gcd(a,b−a)
推广: g c d ( a 1 , a 2 , … , a n ) = g c d ( a 1 , a 2 − a 1 , … , a n − a n − 1 ) gcd(a_1,a_2,\dots,a_n)=gcd(a_1,a_2-a_1,\dots,a_n-a_{n-1}) gcd(a1,a2,…,an)=gcd(a1,a2−a1,…,an−an−1)
所以此题的 g c d ( a 2 − a 1 , … , a n − a n − 1 ) gcd(a_2-a_1,\dots,a_n-a_{n-1}) gcd(a2−a1,…,an−an−1)的 g c d gcd gcd不能改变了,所以此题的 a n s = g c d ( a 2 − a 1 , … , a n − a n − 1 ) ans=gcd(a_2-a_1,\dots,a_n-a_{n-1}) ans=gcd(a2−a1,…,an−an−1)
同时又要使 a 1 a_1 a1满足有因子 a n s ans ans,所以 x = ( a n s − a 1 % a n s ) % a n s x=(ans-a_1\%ans)\%ans x=(ans−a1%ans)%ans
这样就能取最小的 x x x。
另外此题有个坑,差分数组可能有负数,会发生除0错误的情况,取一下绝对值即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5,M=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
ll a[N];
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=n;i>1;i--) a[i]=abs(a[i]-a[i-1]);
ll ans=0;
for(int i=2;i<=n;i++) ans=gcd(ans,a[i]);
printf("%lld %lld\n",ans,(ans-a[1]%ans)%ans);
return 0;
}