题目链接:牛客小白月赛99_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ
通过对题目分析我们可以知道,题目要求我们找到一个时间t,时间t不能被a[i]整除。也就是说,t的因子不能是a[i]。由此我们可以想到,什么数比较容易满足这个条件呢?诶!就是素数(只能被1和它本身整除的数)。但是怎么证明时间t一定是素数呢?
首先我们假设时间t是一个合数,且这个合数不能被a[i]整除。因为t是合数,所以它一定存在一个除了1和它本身以外的因子,假设这个因子是x,那么x也一定满足不能被a[i]整除这一条件。既然x也满足这一条件,并且题目要求我们找的是最小的满足不能被a[i]整除的数,而x<t,那么答案肯定不是t。所以可以证明我们要求的时间t一定不是合数。
不是合数那就是素数了(t不可能为0)。有什么方法可以帮我们找到不被a[i]整除的最小的素数呢?我们自然会想到素数筛算法。
由于n<=2e5,所以我们可以用一个数组prime存储2e5+1个素数。并且我们可以使用map给所有的a[i]打上标记,最后只需要遍历2e5+1个素数,如果prime[i]满足不被a[i]整除的条件,也就是mp[prime[i]]=0,那么prime[i]就是答案。
AC code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
bool vis[1000000005];
int prime[200005];//存储2e5个素数
void pri(int n) {//欧拉筛
int sum = 0;
for (int i = 2; i <= n; i++) {
if (!vis[i]) prime[++sum] = i;
if (sum > 2e5) break;//因为n<=2e5,所以最多存储2e5+1个素数就够了
for (int j = 1; j <= sum && i * prime[j] <= n; j++) {
vis[i * prime[j]] = 1;
if (i % prime[j]==0) break;
}
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> t;
pri(100000000);
while (t--) {
map<int, int>mp;
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
int a;
cin >> a;
mp[a] = 1;//因为a[i]有可能是素数,所以把这个素数打上标记
}
for (int i = 1; i <= 200001; i++) {
if (!mp[prime[i]]) {//如果这个素数不能a[i]整除,那么直接输出
cout << prime[i] << '\n';
break;
}
}
}
return 0;
}