P4549 【模板】裴蜀定理
题目传送门
前置知识:裴蜀定理
分析
对于输入的 n n n个数 a 1 a_1 a1, a 2 a_2 a2, a 3 ⋯ a n a_3\cdots a_n a3⋯an,我们其实可以默认它们全部为非负数,因为对于 x i x_i xi,是可以取任意值的,所以当 a i a_i ai为负时, x i x_i xi取负数,两数之积就为正了,所以不用考虑判断 S < 0 S<0 S<0的情况。
接着,我们其实需要计算的就是 ∣ a 1 ∣ ⋅ x 1 + ∣ a 2 ∣ ⋅ x 2 + ∣ a 3 ∣ ⋅ x 3 + ⋯ + ∣ a n ∣ ⋅ x n \lvert a_1\lvert\cdot x_1+\lvert a_2\lvert\cdot x_2+\lvert a_3\lvert\cdot x_3+\cdots+\lvert a_n\lvert\cdot x_n ∣a1∣⋅x1+∣a2∣⋅x2+∣a3∣⋅x3+⋯+∣an∣⋅xn。
那么,又因为在裴蜀定理及其证明中说过裴蜀定理的推广:
对于多个整数 a 1 a_1 a1, a 2 a_2 a2, a 3 a_3 a3…… a n a_n an(不全为零),存在整数 x 1 x_1 x1, x 2 x_2 x2, x 3 x_3 x3…… x n x_n xn使得:
g c d ( gcd( gcd( a 1 a_1 a1, a 2 a_2 a2, a 3 a_3 a3…… a n a_n an ) = a 1 x 1 + a 2 x 2 + a 3 x 3 + )=a_1x_1+a_2x_2+a_3x_3+ )=a1x1+a2x2+a3x3+…… a n x n a_nx_n anxn且 a 1 x 1 + a 2 x 2 + a 3 x 3 + a_1x_1+a_2x_2+a_3x_3+ a1x1+a2x2+a3x3+…… a n x n a_nx_n anxn为 g c d ( gcd( gcd( a 1 a_1 a1, a 2 a_2 a2, a 3 a_3 a3…… a n a_n an ) ) )的倍数。
那么,原式就可以表示为: p ⋅ g c d ( ∣ a 1 ∣ , ∣ a 2 ∣ , ∣ a 3 ∣ , ⋯ , ∣ a n ∣ ) p\cdot gcd(\lvert a_1\lvert,\lvert a_2\lvert,\lvert a_3\lvert,\cdots,\lvert a_n\lvert) p⋅gcd(∣a1∣,∣a2∣,∣a3∣,⋯,∣an∣),当 S > 0 S>0 S>0时,要使 S S S最小, g c d ( ∣ a 1 ∣ , ∣ a 2 ∣ , ∣ a 3 ∣ , ⋯ , ∣ a n ∣ ) gcd(\lvert a_1\lvert,\lvert a_2\lvert,\lvert a_3\lvert,\cdots,\lvert a_n\lvert) gcd(∣a1∣,∣a2∣,∣a3∣,⋯,∣an∣)为定值,那么 p p p取值为 1 1 1。
所以,最后的答案就是所有 a [ i ] a[i] a[i]的最大公约数。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();return x*f;
}
void print(int x){if(x<0)putchar('-'),x=-x;if(x<10){putchar(x+'0');return;}print(x/10);putchar(x%10+'0');
}
int n,ans;
int a[N];
int gcd(int a,int b){//辗转相除法if(a<b)swap(a,b);if(b==0)return a;return gcd(b,a%b);
}
signed main(){n=read();for(int i=1;i<=n;i++)ans=gcd(ans,abs(read()));print(ans);
}