【题解】Not coprime 题解
本人第一次使用新风格写题解,希望大家多多包涵~
我们先来证明一个结论:
- 答案必然是 ,其中 为 到 内全体质数集合的一个子集。
下面我们分步来论述一下:
-
首先,由于答案是满足每个数都至少有一个质因子是其质因数,我们暂时忽略“质数”这一条件,也就是每个数都有一个因子是其因数,这个很显然,就是最大公因数大于 。而再加上“质数”这个条件,也就是有一个质数公因数。
-
而又由于我们希望这个数尽量的小,因此需要包含尽可能少的因数。而如果答案不是质数的乘积,那必然有一个质数重复乘了几次(即在答案分解质因数后有一个质因数的指数不为 )。
-
不妨设这个数为 ,如果之前 本身就不是给定的数中某个数的质因数,那么乘上之后答案如果满足题意还是满足题意,不满足还是不满足,多此一举。而如果是,那在乘上之前答案本身在这个数上就已经达成了目标(有一个质数公因数),再乘上也是多此一举,综上,答案必为质数的乘积。
-
其次由于 ,而一个数的因数不能超过这个数本身,如果答案中的 超过 ,那么它必然不是任何一个 的因数,相当于这个 就没用,因此 。
由于 到 内全体质数集合的元素个数较小,因此我们可以发挥我们的数学常识将其所有元素默写出来,然后使用二进制枚举状态的方法,枚举每个质数的选和不选,那么把所有选的质数乘起来就是 ,接着判断一下是否跟所有的 都有一个共同的质因数(由于答案为质数相乘,那么相当于判断最大公因数是否大于 )就可以了。
时间复杂度 ,其中 为 到 内全体质数集合的元素个数。
for(int S = 1;S < (1 << 15);S++) //状态
{
int u = 1;
for(int i = 1;i <= 15;i++)
{
if(S & (1 << (i - 1))) u *= p[i]; //计算答案
}
int cnt = 0;
for(int i = 1;i <= n;i++)
{
if(__gcd(a[i], u) > 1) cnt++; //判断有无共同的质因数
}
if(cnt == n) ans = min(ans, u); //更新最小值
}

浙公网安备 33010602011771号