求所有对的最小公倍数组成新集合的最大公约数是多少?
假设 a i a_i ai 没有 2 2 2 这个因子,且 a j a_j aj 也没 2 2 2 这个因子,那么 l c m ( a i , a j ) lcm(a_i , a_j) lcm(ai,aj) 就不包含 2 2 2 这个因子
那么 a n s = g c d { l c m ( a i , a j ) ) ∣ i < j } ans = gcd \{lcm(a_i , a_j)) | i < j\} ans=gcd{lcm(ai,aj))∣i<j} 也就不包含 2 2 2 这个因子
也就是说数组中如果有两个以上的数都不包含某个因子,那么答案也就不包含这个因子
对每个数进行质因子分解,分解后质因子的幂次存于对应质因子的容器中
然后计算答案时判断每个质因子的容器大小是否大于等于 n − 1 n - 1 n−1
如果是则说明数组中少于两个数没有这个质因子,则答案必定要乘上这个质因子
至于是该乘上这个质因子的几次方,我们对容器升序排个序
如果容器的大小等于 n n n 则取第二个元素即次小幂次,如果等于 n − 1 n - 1 n−1 则取第一个元素即最小幂次
以某质数容器的大小为 n n n 举例 :
最后一个元素对应最大幂次,只有一个数包含了这个它,倒数第二个元素对应次大幂次,有两个数包含了它
以此类推第二个元素对应次小幂次,有 n − 1 n - 1 n−1 个数包含了它,第一个元素为最小次幂,有 n n n 个数包含了它
因为只需要 n − 1 n - 1 n−1个数有包含它答案就可以乘上它,所以我们选第二个元素作为幂次。
const int N = 2e5 + 50;
int n, k;
int ans, res, tmp;
int vis[N], a[N], prime[N], cnt;
vector<int> v[N];
void init()
{
vis[1] = 1;
rep(i, 2, N - 10)
{
if (!vis[i])
prime[++cnt] = i;
for (int j = 1; j <= cnt && i * prime[j] <= N - 10; j++)
{
vis[i * prime[j]] = 1;
if (i % prime[j] == 0)
break;
}
}
}
void cal(int x)
{
rep(i, 1, cnt)
{
if (prime[i] * prime[i] > x)
break;
if (x % prime[i] == 0)
{
int num = 0;
while (x % prime[i] == 0)
{
x /= prime[i];
num++;
}
v[prime[i]].pb(num); //质因子分解
}
}
if (x > 1)
v[x].pb(1);//x为质数
}
int main()
{
init();
ans = 1;
sd(n);
rep(i, 1, n)
{
sd(a[i]);
cal(a[i]);
}
rep(i, 1, cnt)
{
int x = prime[i];
sort(v[x].begin(), v[x].end());
if ((v[x].size()) == n)
{
int y = max(v[x][0], v[x][1]);
tmp = 1;
rep(i, 1, y)
tmp *= x;
ans *= tmp;
}
if ((v[x].size()) == n - 1)
{
int y = v[x][0];
tmp = 1;
rep(i, 1, y)
tmp *= x;
ans *= tmp;
}
}
pd(ans);
return 0;
}