C. Orac and LCM
题目链接-C. Orac and LCM


题目大意
给你
n
n
n个数,让求
g
c
d
(
l
c
m
(
a
[
i
]
,
a
[
j
]
)
)
(
i
<
j
)
gcd(lcm(a[i],a[j])) (i<j)
gcd(lcm(a[i],a[j]))(i<j)
解题思路
数
论
数论
数论
- 对于 a [ 1 ] a[1] a[1],其产生的 l c m lcm lcm有 l c m ( a [ 1 ] , a [ 2 ] ) 、 l c m ( a [ 1 ] , a [ 3 ] ) 、 . . . l c m ( a [ 1 ] , a [ n ] ) lcm(a[1],a[2])、lcm(a[1],a[3])、...lcm(a[1],a[n]) lcm(a[1],a[2])、lcm(a[1],a[3])、...lcm(a[1],a[n]),则它们的最大公因数 g c d 1 = g c d ( l c m ( a [ 1 ] , a [ 2 ] ) 、 l c m ( a [ 1 ] , a [ 3 ] ) 、 … l c m ( a [ 1 ] , a [ n ] ) ) gcd1=gcd(lcm(a[1],a[2])、lcm(a[1],a[3])、…lcm(a[1],a[n])) gcd1=gcd(lcm(a[1],a[2])、lcm(a[1],a[3])、…lcm(a[1],a[n]))
- 观察发现它们中的每一项都含有公因子 a [ 1 ] a[1] a[1],故 a [ 1 ] a[1] a[1]必为 g c d 1 gcd1 gcd1的因子,所以可化简为 g c d 1 = l c m ( a [ 1 ] , g c d ( a [ 2 ] , a [ 3 ] , . . . a [ n ] ) ) gcd1=lcm(a[1],gcd(a[2],a[3],...a[n])) gcd1=lcm(a[1],gcd(a[2],a[3],...a[n]))
- 同理可得 g c d 2 、 g c d 3 … g c d n gcd2、gcd3…gcdn gcd2、gcd3…gcdn,那么答案可表示为 g c d ( g c d 1 , g c d 2 , . . . g c d n ) gcd(gcd1,gcd2,...gcdn) gcd(gcd1,gcd2,...gcdn)
- 我们可以反向遍历数组
a[],用suf[]数组储存后缀gcd,然后再计算每个数与它后缀suf[] - 具体操作见代码
附上代码
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) (x &(-x))
#define endl '\n'
using namespace std;
const int INF=0x3f3f3f3f;
const int dir[4][2]={-1,0,1,0,0,-1,0,1};
const double PI=acos(-1.0);
const double e=exp(1.0);
const double eps=1e-10;
const int M=1e9+7;
const int N=1e6+10;
typedef long long ll;
typedef pair<int,int> PII;
typedef unsigned long long ull;
int gcd(int a,int b) {
return b?gcd(b,a%b):a;
}
int a[N],suf[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,ans=0;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=n;i>0;i--)
suf[i]=gcd(a[i],suf[i+1]);
for(int i=1;i<=n;i++)
ans=gcd(ans,suf[i+1]*a[i]/gcd(suf[i+1],a[i]));
cout<<ans<<endl;
return 0;
}

本文介绍了一道数论题目“C. Orac and LCM”的解题思路,通过分析给定数组中两两元素的最小公倍数与最大公约数的关系,提出了一种高效的算法来求解所有可能对的最大公约数。

553

被折叠的 条评论
为什么被折叠?



