C - Orac and LCM(数学,思维,1600)

题目传送门

题意: 给你n个数,输出所有数对的最小公倍数的最大公约数。

思路: 我们对于某个数a[i],只要看他和[i+1,n]的每个数的最小公倍数,因为前面的部分会由前面的数和a[i]去组合,我们不用重复计算。假如要求a对b、c的lcm 的gcd ,也就是gcd(a* b/gcd(a,b),a* c/gcd(a,c)) ,相当于a*gcd(b/gcd(a,b),c/gcd(a,c)), 实际上就是a*gcd(b,c)/gcd(a,b,c) ,所以我们可以考虑一手求后缀的gcd,依次转移。

解释
a * gcd(b/gcd(a,b),c/gcd(a,c))=a * gcd(b,c)/gcd(a,b,c)
我们把gcd(b/gcd(a,b),c/gcd(a,c))换成gcd(b,c)后,它们可能并不相等,因为有可能gcd(a,b)和gcd(a,c)有公共部分(公共因子),这样我们就相当于把它扩大了gcd(gcd(a,b),gcd(a,c))倍,即gcd(a,b,c)倍,所以我们要除掉这个公共。

代码

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define vi vector<int>
#define mii map<int,int>
#define pii pair<int,int>
#define ull unsigned long long
#define all(x) x.begin(),x.end()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n";
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f;}
using namespace std;
const int N=1e5+5;
const int inf=0x7fffffff;
const int mod=998244353;
const double eps=1e-6;
int a[N],g[N];
signed main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    g[n]=a[n];
    g[n-1]=__gcd(a[n],a[n-1]);
    int res=a[n]/g[n-1]*a[n-1];
    for(int i=n-2;i>=1;i--)
    {
        g[i]=__gcd(g[i+1],a[i]);
        res=__gcd(res,a[i]/g[i]*g[i+1]);
    }
    cout<<res<<endl;
}

原创文章 144 获赞 13 访问量 8659

猜你喜欢

转载自blog.csdn.net/Joker_He/article/details/106106079