CF1349A 【Orac and LCM】
阿新 • • 發佈:2020-08-23
題目大意:
給你一個長度為 \(n\) 的集合 \(\{a_1 , a_2\;...\;a_n\}\),請你求出 \(\gcd\{ \text{lcm}(a_i,a_j)\;|\;i < j \}\)
思路:
眾所周知,\(\text{lcm}(a,b)=\dfrac{a\times b}{\gcd(a,b)}\)
所以原式可以化為 \(\gcd\{ \dfrac{a_i\times a_j}{\gcd(a_i,a_j)}\;|\;i < j \}\)
把 \(\gcd(a_i,a_j)\) 提出可得 \(\dfrac{\gcd\{ a_i\times a_j\;|\;i < j \}}{\gcd(a_1,a_2 \;...\;a_n)}\)
\(\gcd(a_1,a_2 \;...\;a_n)\) 可以線性求出,那麼問題就轉化成了如何快速求 \(\gcd\{ a_i\times a_j\;|\;i < j \}\)
設我們每次列舉到第 \(i\) 個數 \(a_i\) 為 \(x\),那麼可以將 \(\gcd\{ x\times a_j\;|\;i < j \}\) 中的 \(x\) 提出,就可以得到 \(x \times \gcd(a_{i+1},a_{i+2}\;...\;a_{n})\)。
可以預處理出一個字尾 \(\gcd\) ,然後列舉 \(a_i\) 計算答案即可。
時間複雜度:常數極小的 \(\text{O}(n \log a_{max})\)
記得開 \(\text{long long}\) ((
Code:
#include<bits/stdc++.h> #define LL long long using namespace std; LL read() { LL ans=0,f=1; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } const LL N=1e5+5; LL n,a[N],b[N],ans; int main() { n=read(); for(LL i=1;i<=n;++i) a[i]=read(); for(LL i=n;i>=1;--i) // 預處理字尾 gcd b[i]=__gcd(b[i+1],a[i]); for(LL i=1;i<=n;++i) // 計算 gcd { ai , aj | i < j } ans=__gcd(ans,a[i]*b[i+1]); // 答案就是 gcd { ai , aj | i < j } / gcd ( a1 , a2 ... an ) printf("%lld\n",ans/b[1]); return 0; }