公因子(gcd性质)

公因子(gcd性质)

传送门

思路:

g c d gcd 性质: g c d ( a , b ) = g c d ( 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})

所以此题的 g c d ( a 2 a 1 , , a n a n 1 ) gcd(a_2-a_1,\dots,a_n-a_{n-1}) g c d 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})

同时又要使 a 1 a_1 满足有因子 a n s ans ,所以 x = ( a n s a 1 % a n s ) % a n s x=(ans-a_1\%ans)\%ans

这样就能取最小的 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/106980276