传送门
题意是输入两组数 $\\{a\\}$ 和 $\\{b\\}$,要求判断 $A=\prod_{i=1}^na_i$ 除以 $B=\prod_{i=1}^mb_i$ 是否为质数,如果是则输出 YES
否则输出 NO
。
太蒟蒻了只做出来第一题 QAQ
数据范围中 $n$ 和 $m$ 都可以到达 $10^5$ 级别,而且单个的数 $a_i$ 和 $b_i$ 达到了 $10^{12}$ 的数量级,显然不能用朴素的方法做(即使自带高精的 Python 也存不下这么多位数吧)
我们发现输入的都是两个天文数字的因子,显然当一个数拥有除 1 以外的两个及以上的因子时不是质数。还有一个很重要的条件就是对于任意一个数字,保证其在 $b_i$ 中出现的次数不多于在 $a_i$ 中出现的次数,也就是说,可以约去相同的数字!
怎么办呢?可以考虑拿 STL 自带的 map 构造映射,用来记录每个因子出现的次数,map<long long, int> cnt
,其中 Key
是输入的因子,Value
是这个因子出现的次数(map<Key, Value>
)。输入第一个数 $A$ 的时候,我们在统计时加上因子出现的次数,输入第二个数 $B$ 的时候减去因子出现的个数(相当于约分了),这样 map 记录的应该是最终除法计算的结果的因子。
接下来就好办了。只要 map 的大小大于 1,那么说明它一定存在两个或以上的不同因子,一定不是质数,输出 NO
即可。
然后如果 map 的大小等于 1 的话,就看这个数出现的次数了,如果出现的次数大于 1,那么它一定也不是质数。
最后如果这个数只出现了一次,说明结果就是这个数,只要用 $O(\sqrt{N})$ 的算法判断这个数是否是质数就可以了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxN = 1e5 + 3;
int T, n, m;
template<typename Tp> void read(Tp &x) {
char c = getchar();
x = 0;
while (!isdigit(c)) c = getchar();
do {
x = (x * 10) + (c ^ 48);
c = getchar();
} while (isdigit(c));
}
bool isprime(long long x) {
long long tmp = sqrt(x);
for (long long i = 2; i <= tmp; i++)
if (!(x % i)) return false;
return true;
}
int main() {
read(T);
while (T--) {
map<long long, int> cnt;
read(n), read(m);
for (int i = 1; i <= n; i++) {
long long num;
read(num);
if (num == 1) continue;
cnt[num]++;
}
for (int i = 1; i <= m; i++) {
long long num;
read(num);
if (num == 1) continue;
if(!(--cnt[num]))
cnt.erase(num);
}
if (cnt.size() != 1) printf("NO\n");
else {
long long num = cnt.begin()->first;
int sum = cnt.begin()->second;
if (sum != 1) printf("NO\n");
else if (isprime(num)) printf("YES\n");
else printf("NO\n");
}
}
}