Orac and LCM(GCD/LCM/质因子分解/推导证明)Codeforces Round #641 (Div. 2) C题
程序员文章站
2022-06-03 19:38:34
...
题目大意
给个数,求.
分析过程
考虑每个数的素因子分解,对于的所有组合,对应的素因子总满足,即取二者最大的那一个,而对于来说则是取。于是,对于结果来说,一定有一个唯一的素数分解,其中每一个素数的等于所有组合中的最小值,而对于所有来说,能够得到的最小值是所有的的次小值,因为最小的那个肯定会由于的特性被掩盖掉,而当最小的和次小的对应的在一起求时,次小的那个对应的会被保留下来。
所以,这道题先用类似于埃拉斯托特尼筛选法的方式预处理标记一遍的最小素因子,然后对于每个进行素因子分解,然后维护对应素因子的最小值和次小值即可。
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;
}
上一篇: js笔试题-接收get请求参数
下一篇: umi和弓道 计算几何 详解