https://codeforces.com/contest/1350/problem/C
C. Orac and LCM
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
For the multiset of positive integers s={s1,s2,…,sk}s={s1,s2,…,sk}, define the Greatest Common Divisor (GCD) and Least Common Multiple (LCM) of ss as follow:
- gcd(s)gcd(s) is the maximum positive integer xx, such that all integers in ss are divisible on xx.
- lcm(s)lcm(s) is the minimum positive integer xx, that divisible on all integers from ss.
For example, gcd({8,12})=4,gcd({12,18,6})=6gcd({8,12})=4,gcd({12,18,6})=6 and lcm({4,6})=12lcm({4,6})=12. Note that for any positive integer xx, gcd({x})=lcm({x})=xgcd({x})=lcm({x})=x.
Orac has a sequence aa with length nn. He come up with the multiset t={lcm({ai,aj}) | i<j}t={lcm({ai,aj}) | i<j}, and asked you to find the value of gcd(t)gcd(t) for him. In other words, you need to calculate the GCD of LCMs of all pairs of elements in the given sequence.
Input
The first line contains one integer n (2≤n≤100000)n (2≤n≤100000).
The second line contains nn integers, a1,a2,…,ana1,a2,…,an (1≤ai≤2000001≤ai≤200000).
Output
Print one integer: gcd({lcm({ai,aj}) | i<j})gcd({lcm({ai,aj}) | i<j}).
Examples
input
Copy
2 1 1
output
Copy
1
input
Copy
4 10 24 40 80
output
Copy
40
input
Copy
10 540 648 810 648 720 540 594 864 972 648
output
Copy
54
Note
For the first example, t={lcm({1,1})}={1}t={lcm({1,1})}={1}, so gcd(t)=1gcd(t)=1.
For the second example, t={120,40,80,120,240,80}t={120,40,80,120,240,80}, and it's not hard to see that gcd(t)=40gcd(t)=40.
题意:先求所有数字中任意两数字的LCM,再求所有LCM的GCD.
思路:首先要了解lcm和gcd的本质:
根据算术基本定理:
而
例:
因此,在任意两数LCM时,求的就是两数公共素数因子的次方较大值,而再求gcd就是求所有较大值中的最小值,记录每个素数的次方值并排序,如果n个数都有此素因子,则求完任意两个较大值后求出的较小值就是所有次方值的第二小值,如果n-1个数有此素因子,则是所有次方值的第二小值,其他情况则有只是两个0,求较大值后为0,再求较小值还为0,即不在结果中。
例:
4
10 24 40 80
2 : 1 3 3 4 LCM:3 3 4 3 4 4 (任意两者较大值)LCM的GCD:3(LCM所有值中的最小值)
3 :0 1 0 0 LCM:1 0 0 1 1 0 LCM的GCD:0
5:1 0 1 1 LCM: 1 1 1 1 1 1 LCM的GCD:1
则答案为:2^3 * 5 = 40
#include<iostream>
#include<algorithm>
#define ll long long
#include<vector>
using namespace std;
const int N = 100000 + 10;
const int M = 200000 + 10;
ll prime[M];
ll num[N];
vector<ll> v[M];
ll vis[M];
ll cnt;
ll ksm(ll a, ll b)
{
ll rul = 1;
while(b)
{
if(b & 1) rul = rul * a;
b >>= 1;
a *= a;
}
return rul;
}
void getprime()
{
for(ll i=2; i<M; i++)
{
if(!vis[i])
{
prime[cnt++] = i;
for(ll j=i+i; j<M; j+=i)
{
vis[j] = 1;
}
}
}
}
int main()
{
getprime();
ll n;
cin>>n;
for(ll i=1; i<=n; i++)
{
scanf("%lld",&num[i]);
for(ll j=0; j<cnt&&num[i]>=prime[j]*prime[j]; j++)//注意剪枝,否则TL
{
if(num[i] % prime[j] == 0)
{
ll tem = 0;
while(num[i] % prime[j] == 0)
{
num[i] /= prime[j];
tem++;
}
v[prime[j]].push_back(tem);
}
}
if(num[i] > 1) v[num[i]].push_back(1);
}
for(ll i=0; i<cnt; i++)
{
sort(v[prime[i]].begin(), v[prime[i]].end());
}
ll ans = 1;
for(ll i=0; i<cnt; i++)
{
if(v[prime[i]].size() == n) ans *= ksm(prime[i], v[prime[i]][1]);
else if(v[prime[i]].size() == n-1) ans *= ksm(prime[i], v[prime[i]][0]);
}
cout<<ans;
return 0;
}