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<j}),

即对任意两个不同下标(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<bits/stdc++.h>
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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值