Codeforces Round #641 (Div. 1) A. Orac and LCM(数论 gcd与lcm性质)

题目

n(2<=n<=1e5)个数的数组a[],满足ai(1<=ai<=2e5)

求gcd({lcm({ai,aj}) | i

即对任意两个不同下标(i,j),求其最小公倍数lcm(i,j)

再对这C(n,2)个结果,求其最大公约数gcd

思路来源

题解

题解

1600的题也要总结,我也太废物了吧……

①一个比较直观好做的做法,枚举素因子pi,

考虑pi在至少n-1个数中都出现才可以被保留下来,否则两个pi的0次幂其gcd一定为1

如果在n个数中均出现,答案是次小的幂次,lcm(p_{i}^{first},p_{i}^{second}})=pi^{second}

如果在n-1个数中出现,说明最小的幂次是0,即lcm(pi^0,pi^{first})=pi^{first}

②真正想总结的是这个做法,

考虑n=3,gcd(lcm(a1,a2),lcm(a1,a3),lcm(a2,a3))=gcd(gcd(lcm(a1,a2),lcm(a1,a3)),gcd(lcm(a2,a3)))

把含a1项搞出来,求个gcd,含a2项搞出来求个gcd,…,之后再两两求gcd

先给结论:gcd(lcm(a1,a2),lcm(a1,a3),...,lcm(a1,an))=lcm(a1,gcd(a2,...,an))

证这个结论,可以考虑对每个素因子证,gcd是对幂次取min,lcm是取max

等价于证min(max(a1,a2),max(a1,a3),...,max(a1,an))=max(a1,min(a2,...,an))

于是分a1\leq min(a2,...,an)还是大于,讨论一下就证完了

有了化简之后的式子,维护一个后缀gcd,就做完了

代码

#include
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define sci(a) scanf("%d",&(a))
typedef long long ll;
const int N=1e5+10;
ll lcm(ll x,ll y){
    return x/__gcd(x,y)*y;
}
int n;
ll a[N],suf[N],ans;
int main(){
    sci(n);
    rep(i,1,n){
        scanf("%lld",&a[i]);
    }
    suf[n]=a[n];
    per(i,n-1,1){
        suf[i]=__gcd(suf[i+1],a[i]);
    }
    ans=lcm(a[1],suf[2]);
    rep(i,2,n-1){
        ans=__gcd(ans,lcm(a[i],suf[i+1]));
    }
    printf("%lld\n",ans);
    return 0;
}

 

你可能感兴趣的:(数论)