-
题意:给你一个数列,求所有子序列对的\(lcm\),然后求这些所有\(lcm\)的\(gcd\).
-
题解:我们对所有数分解质因数,这里我们首先要知道一个定理:
对于\(n\)个数,假如某个质数\(p\),这\(n\)个数中有\(\le n-1\)个数的质因数包含\(p\),那么他们的\(lcm\)中一定不含\(p\)这个因数,随意我们先预处理出每个数的质因子,选择个数\(\ge n-1\)的质因子.
然后,在这些质因子中,我们要求每两两之间的\(lcm\),然后再求他们的\(gcd\),不难发现,他们最后得到的\(gcd\)一定是那些\(lcm\)中最小的数,而\(lcm\)最小的数一定是不同次相同底第二小的数(包括1).
所以,假如\(p\)的数量为\(n\),那么就选次数第二小的,如果为\(n-1\),就选最小的(因为1肯定比它小).
最后,累乘一下就行了.
-
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <vector> #include <map> #include <set> #include <unordered_set> #include <unordered_map> #define ll long long #define fi first #define se second #define pb push_back #define me memset const int N = 1e6 + 10; const int mod = 1e9 + 7; using namespace std; typedef pair<int,int> PII; typedef pair<long,long> PLL; int n; ll x; vector<ll> Hash[N]; void divide(ll x){ ll cnt=0; for(ll i=2;i<=x/i;++i){ if(x%i==0){ cnt=0; while(x%i==0){ x/=i; cnt++; } Hash[i].pb(cnt); } } if(x>1) Hash[x].pb(1); } ll fpow(ll a,ll k){ ll res=1; while(k){ if(k&1) res=res*a; k>>=1; a=a*a; } return res; } int main() { ios::sync_with_stdio(false); cin>>n; for(ll i=1;i<=n;++i){ cin>>x; divide(x); } ll ans=1; for(ll i=1;i<=200000;++i){ if(Hash[i].size()>=n-1){ sort(Hash[i].begin(),Hash[i].end()); if(Hash[i].size()==n) ans*=fpow(i,Hash[i][1]); else ans*=fpow(i,Hash[i][0]); } } printf("%lld\n",ans); return 0; }