CF1350C Orac and LCM(前缀和+数论)

题意:

给出一个序列,两两之间的最小公倍数可以组成一个集合,计算这个集合的最大公因数。

题解:

第三题一般不会涉及算法,还是要向二分或前缀和的方向想一下。对于a1与剩下所有的数组成的最小公倍数,可以推导出:

gcd(lcm(a1,a2),lcm(a1,a3)....lcm(a1,an)) = lcm(a1,gcd(a2,a3,...,an))。

对于每个数都是如此,所以我们求出每个序列后缀的gcd就可以了。

#include<bits/stdc++.h>
 
using namespace std;
 
const int maxn=1e5+100;
typedef long long ll;
ll a[maxn];
ll t[maxn];//保存后缀gcd
ll Lcm[maxn];//保存以每个数为起点的最小公倍数集合的最大公因数
int n;
ll lcm (ll x,ll y) {
    return x*y/__gcd(x,y);
}
int main () {
    cin>>n;
    for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    t[n]=a[n];
    for (int i=n-1;i>=1;i--) t[i]=__gcd(t[i+1],a[i]);
    for (int i=1;i<=n;i++) Lcm[i]=lcm(a[i],t[i+1]);
    ll ans=Lcm[1];
    for (int i=2;i<=n;i++) ans=__gcd(ans,Lcm[i]);
    printf("%lld\n",ans);
}

 

posted @ 2020-05-23 15:12  zlc0405  阅读(248)  评论(0编辑  收藏  举报