题目 | Hossam and Trainees
Codeforces Round #837 (Div. 2)
C. Hossam and Trainees
https://codeforces.com/contest/1771/problem/B
3 seconds / 256 megabytes
standard input / standard output
Problem
Hossam has $n$ trainees. He assigned a number $a_i$ for the $i$-th trainee.
A pair of the $i$-th and $j$-th ($i \neq j$) trainees is called successful if there is an integer $x$ ($x \geq 2$), such that $x$ divides $a_i$, and $x$ divides $a_j$.
Hossam wants to know if there is a successful pair of trainees.
Hossam is very tired now, so he asks you for your help!
Input
The input consists of multiple test cases. The first line contains a single integer $t$ ($1 \le t \le 10^5$), the number of test cases. A description of the test cases follows.
The first line of each test case contains an integer number $n$ ($2 \le n \le 10^5$).
The second line of each test case contains $n$ integers, the number of each trainee $a_1, a_2, \dots, a_n$ ($1 \le a_i \le 10^9$).
It is guaranteed that the sum of $n$ over all test cases does not exceed $10^5$.
Output
Print the answer — "YES" (without quotes) if there is a successful pair of trainees and "NO" otherwise. You can print each letter in any case.
Example
Input
2
3
32 48 7
3
14 5 9
Output
YES
NO
Note
In the first example, the first trainee and the second trainee make up a successful pair:
$a_1 = 32, a_2 = 48$, you can choose $x = 4$.
题解
典型错解 - 看起来仿佛是 $O(n)$
拿到题目一眼看到就想到把整个数列求一个和得到 $mul$,再吧整个数列求一个最小公倍数得到 $lcm$,如果 $mul=lcm$ 则输出 NO,否则输出 YES. 这个解法在数学上是没有任何问题的,复杂度也是 $O(n)$,样例也是能通过的。
但是该解发存在的问题就是连续乘法会让数字大小呈指数趋势增长,$mul$ 和 $lcm$ 这两个变量会以非常快的速度溢出然后错误。如果使用高精度算法,该数字也会变得非常巨大,长度可以达到 $9\times10^5$,是不可能在合理的时间计算出结果的。
正确解法 - $O(n\log n)$
将数列中每个数分解质因数,如果有任意两个数含有同一个质因子,则输出 YES,如果所有数都没有公共的质因子,则输出 NO.
从头到尾遍历数列,使用集合 $s$ 来储存出现过的质因子:
- 对于每个数,分解质因数得到:$n=p_1^{a_1}p_2^{a_2}\dots p_n^{a_n}$
考虑其所有的质因子:$p_1,p_2,\dots,p_n$
- 若质因子 $p_i$ 已经在 $s$ 中:直接输出 YES,结束本次计算
- 若质因子 $p_i$ 不在 $s$ 中:将 $p_i$ 加入 $s$
- 若遍历完整个数列后还没有找到相同的质因子,则输出 NO,结束计算
对于一个数 $n$ ,其质因子个数一定 $\leq\log_2{n}$,当 $n=10^9$ 时,$\log_2{n}=29.89$,是很小的规模。因此该算法的最差时间复杂度为 $O(n\log{n})$,可以满足时限要求。
代码
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int MAXN = 1e5 + 10;
int a[MAXN], prime[MAXN], primesize = 0;
bool not_prime[MAXN];
void init_prime()
{
not_prime[0] = not_prime[1] = true;
for (int i = 2; i < MAXN; i++)
{
if (!not_prime[i])
prime[primesize++] = i;
for (int j = 0; j < primesize && i * prime[j] < MAXN; j++)
{
not_prime[i * prime[j]] = true;
if (i % prime[j] == 0)
break;
}
}
}
void solve()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
set<int> s;
for (int i = 0; i < n; i++)
{
for (int j = 0; prime[j] * prime[j] <= a[i]; j++)
{
if (!(a[i] % prime[j]))
{
if (s.find(prime[j]) != s.end())
{
cout << "YES" << endl;
return;
}
s.insert(prime[j]);
while (!(a[i] % prime[j]))
a[i] /= prime[j];
}
}
if (a[i] > 1)
{
if (s.find(a[i]) != s.end())
{
cout << "YES" << endl;
return;
}
s.insert(a[i]);
}
}
cout << "NO" << endl;
return;
}
signed main()
{
init_prime();
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi