Codeforces 1350 C. Orac and LCM
原创
©著作权归作者所有:来自51CTO博客作者wx63db9cf49ed95的原创作品,请联系作者获取转载授权,否则将追究法律责任
题意;
求所有对的最小公倍数组成新集合的最大公约数是多少?
假设 没有 这个因子,且 也没 这个因子,那么 就不包含
那么 也就不包含
也就是说数组中如果有两个以上的数都不包含某个因子,那么答案也就不包含这个因子
对每个数进行质因子分解,分解后质因子的幂次存于对应质因子的容器中
然后计算答案时判断每个质因子的容器大小是否大于等于
如果是则说明数组中少于两个数没有这个质因子,则答案必定要乘上这个质因子
至于是该乘上这个质因子的几次方,我们对容器升序排个序
如果容器的大小等于 则取第二个元素即次小幂次,如果等于
以某质数容器的大小为
最后一个元素对应最大幂次,只有一个数包含了这个它,倒数第二个元素对应次大幂次,有两个数包含了它
以此类推第二个元素对应次小幂次,有 个数包含了它,第一个元素为最小次幂,有
因为只需要 个数有包含它答案就可以乘上它,所以我们选第二个元素作为幂次。
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;
}