CF2029E 题解
引理 1:2 可以生成任意合数。
证明:归纳法。显然
对于更大的合数
如果
否则,
引理 2:质数只能被它自己生成。
证明:假设
正解 Part 1:没有质数或有多于一种质数
由引理,没有质数时显然
引理 3:偶数 x 可以被质数 p 生成的充要条件是 2p\le x 。
证明:如果
如果
引理 4:设奇合数 x 的最小质因子为 p_0 ,则它可以被质数 p 生成的充要条件是 2p\le x-p_0 。
证明:显然
如果
如果
考虑可以通过一步操作生成
但
所以对于任意可以生成
然而
所以,
正解 Part 2:判断一个质数的合法性
现在序列中有恰好一种质数,我们只需要判断其合法性即可。
根据引理 3 和引理 4,我们实际上只需要将质数
至此,我们在
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=400007;
ll T,n,a[N],prime[N],nP,x,rem[N];
bool ok[N];
void initPrime(ll n=N-1){
ok[1]=1;
for (int i=2;i<N;++i){
if (!ok[i]) prime[++nP]=i;
for (int j=1;j<=nP&&i*prime[j]<=n;++j){
ll o=i*prime[j];
ok[o]=1;
if (o%2==0) rem[o]=o/2;
else rem[o]=prime[j]*(i-1)/2;
if (i%prime[j]==0) break;
}
}
}
int main(){
initPrime();
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>T;
while(T--){
cin>>n;x=0;
for (int i=1;i<=n;++i) cin>>a[i];
for (int i=1;i<=n;++i) if (!ok[a[i]]){
if (x==0||x==a[i]) x=a[i];else x=-1;
}
if (x==-1){
cout<<x<<'\n';continue;
}
if (x==0){
cout<<"2\n";continue;
}
for (int i=1;i<=n;++i) if (x!=a[i]&&rem[a[i]]<x) x=-1;
cout<<x<<'\n';
}
return 0;
}