題目大意
給個數,求.
分析過程
考慮每個數的素因子分解,對於的所有組合,對應的素因子總滿足,即取二者最大的那一個,而對於來說則是取。於是,對於結果來說,一定有一個唯一的素數分解,其中每一個素數的等於所有組合中的最小值,而對於所有來說,能夠得到的最小值是所有的的次小值,因爲最小的那個肯定會由於的特性被掩蓋掉,而當最小的和次小的對應的在一起求時,次小的那個對應的會被保留下來。
所以,這道題先用類似於埃拉斯托特尼篩選法的方式預處理標記一遍的最小素因子,然後對於每個進行素因子分解,然後維護對應素因子的最小值和次小值即可。
Another Solution
還有一種做法,利用公式
這樣只需要求前綴和後綴就行了。
關於這個公式的證明留個坑,等之後來填~!
AC代碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
const int N = 200000;
ll flag[N+5], a[maxn], cnt[N+5][3], n;
void preTreat(){
int i, j;
for(i=2;i<=N;++i){ //預處理標記每個數能夠被整除的最小素因子
if(flag[i]) continue;
for(j=i;j<=N;j+=i){
if(!flag[j]) flag[j] = i;
}
}
for(i=1;i<=N;++i) cnt[i][0] = cnt[i][1] = N;
}
void solve(){
int i;
ll ans = 1;
for(i=1;i<=n;++i){
while(a[i] > 1){
ll c = 0, temp = a[i];
while(a[i] % flag[temp] == 0){
a[i] /= flag[temp];
++c;
}
if(c < cnt[flag[temp]][0]) swap(cnt[flag[temp]][0], c);
if(c < cnt[flag[temp]][1]) swap(cnt[flag[temp]][1], c);
++cnt[flag[temp]][2]; //記錄此因子存在於多少個樹中
}
}
for(i=2;i<=N;++i){
if(cnt[i][2] < n - 1) continue;
ll j = cnt[i][1];
if(cnt[i][2] == n - 1) j = cnt[i][0];
while(j--) ans *= i;
}
cout<<ans;
}
int main(){
int i;
ios::sync_with_stdio(false);
cin>>n;
for(i=1;i<=n;++i) cin>>a[i];
preTreat();
solve();
return 0;
}