#641 (Div. 2)C. Orac and LCM

題目描述

For the multiset of positive integers s={s1,s2,…,sk}, define the Greatest Common Divisor (GCD) and Least Common Multiple (LCM) of s as follow:
gcd(s) is the maximum positive integer x, such that all integers in s are divisible on x.
lcm(s) is the minimum positive integer x, that divisible on all integers from s.
For example, gcd({8,12})=4,gcd({12,18,6})=6 and lcm({4,6})=12. Note that for any positive integer x, gcd({x})=lcm({x})=x.
Orac has a sequence a with length n. He come up with the multiset t={lcm({ai,aj}) | i<j}, and asked you to find the value of 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).
The second line contains n integers, a1,a2,…,an (1≤ai≤200000).

Output

Print one integer: gcd({lcm({ai,aj}) | i<j}).

Examples

input
2
1 1
output
1
input
4
10 24 40 80
output
40
input
10
540 648 810 648 720 540 594 864 972 648
output
54

Note

For the first example, t={lcm({1,1})}={1}, so gcd(t)=1.
For the second example, t={120,40,80,120,240,80}, and it’s not hard to see that gcd(t)=40.

題目大意

給出n個數,讓你給這些數兩兩之間求最小公倍數。再求出這些最小公倍數的最大公約數。

題目分析

先預處理出2e5以內的素數。
假設a[i]和a[j]都沒有2這個因子,那麼lcm(a[i],a[j])也就沒有2這個因子。那麼ans中也就沒有2這個因子。因爲如果某個質因子p能存在於最後的gcd中,那說明p在所有lcm(a[i],a[j])中都出現了,也就是說最多只能有一個a[i]可以不包含p。

因此,我們可以將這n個數進行拆分,拆分成某個素數的k次冪,並將k存到對應的容器中(可以用鄰接表),如:20可以拆成22和51,然後在pre[2]中放入2,pre[5]中放入1。

最後遍歷每一個素數對應的容器,當該容器中的數小於n-1時,說明ans不包含該容器對應的質因數。
然後我們要分類討論容器中的數爲n和n-1時的情況。
1.容器中的數爲n時,ans中的對應因子爲該素數在容器中的次小值次冪。
2.容器中的數爲n-1時,ans中的對應因子爲該素數在容器中的最小值次冪。

代碼如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <map>
#include <unordered_map>
#include <queue>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <iomanip>
#define LL long long
using namespace std;
int const N=2e5+15,M=1e6;
int prime[N],cnt;
bool st[M];
vector<int> pre[N];     //存將輸入數拆分後對應的冪的容器
void get_prime(int x)   //篩素數(線性篩法)
{
    for(int i=2;i<x;i++)
    {
        if(!st[i]) prime[cnt++]=i;
        for(int j=0;prime[j]<=x/i;j++)
        {
            st[prime[j]*i]=true;
            if(i%prime[j]==0) break;
        }
    }
}
void cal(int x)     //拆分函數,將輸入的數拆分
{
	for(int i=0;i<cnt;i++)
	{
		if(prime[i]*prime[i]>x) break;
		if(x%prime[i]==0)
		{
			int num=0;
			while(x%prime[i]==0)    //將其拆分爲p的num次冪
			{
				num++;
				x/=prime[i];
			}
			pre[prime[i]].push_back(num);   //將num放入容器中
		}
	}
	if(x>1) pre[x].push_back(1);    //若x>1,說明x爲一個素數,將其放入容器
}
int main()
{
	int n;
	cin>>n;
	get_prime(2e5+10);     //預處理2e5以內的素數
	for(int i=1;i<=n;i++)  //輸入n個數並將其拆分
	{
		int x;
		cin>>x;
		cal(x);
	}
	LL ans=1;
	for(int i=0;i<cnt;i++)     //遍歷素數
	{
		int x=prime[i];
		sort(pre[x].begin(),pre[x].end());  //將容器中的數排序
		if(pre[x].size()==n)      //分類討論的兩種情況
		{
			int m=pre[x][1];
			int t=1;
			for(int i=1;i<=m;i++)   //t即爲ans的對應因子
			t*=x;
			
			ans*=t;       //乘上該因子
		}
		else if(pre[x].size()==n-1)
		{
			int m=pre[x][0];
			int t=1;
			for(int i=1;i<=m;i++)
			t*=x;
			
			ans*=t;
		}
	}
	cout<<ans<<endl;     //輸出答案
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章