Codeforces 1350 C. Orac and LCM_质因子

题意;

求所有对的最小公倍数组成新集合的最大公约数是多少?

假设 Codeforces 1350 C. Orac and LCM_质因子分解_02 没有 Codeforces 1350 C. Orac and LCM_数组_03 这个因子,且 Codeforces 1350 C. Orac and LCM_质因子_04 也没 Codeforces 1350 C. Orac and LCM_数组_03 这个因子,那么 Codeforces 1350 C. Orac and LCM_质因子_06 就不包含 Codeforces 1350 C. Orac and LCM_数组_03

那么 Codeforces 1350 C. Orac and LCM_数组_08 也就不包含 Codeforces 1350 C. Orac and LCM_数组_03

也就是说数组中如果有两个以上的数都不包含某个因子,那么答案也就不包含这个因子

对每个数进行质因子分解,分解后质因子的幂次存于对应质因子的容器中

然后计算答案时判断每个质因子的容器大小是否大于等于 Codeforces 1350 C. Orac and LCM_质因子分解_10

如果是则说明数组中少于两个数没有这个质因子,则答案必定要乘上这个质因子

至于是该乘上这个质因子的几次方,我们对容器升序排个序

如果容器的大小等于 Codeforces 1350 C. Orac and LCM_数组_11 则取第二个元素即次小幂次,如果等于 Codeforces 1350 C. Orac and LCM_质因子分解_10

以某质数容器的大小为 Codeforces 1350 C. Orac and LCM_数组_11

最后一个元素对应最大幂次,只有一个数包含了这个它,倒数第二个元素对应次大幂次,有两个数包含了它

以此类推第二个元素对应次小幂次,有 Codeforces 1350 C. Orac and LCM_质因子分解_10 个数包含了它,第一个元素为最小次幂,有 Codeforces 1350 C. Orac and LCM_数组_11

因为只需要 Codeforces 1350 C. Orac and LCM_质因子分解_10个数有包含它答案就可以乘上它,所以我们选第二个元素作为幂次。

AC代码:

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;
}