专栏文章
题解:CF2029E Common Generator
CF2029E题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqde14a
- 此快照首次捕获于
- 2025/12/04 02:58 3 个月前
- 此快照最后确认于
- 2025/12/04 02:58 3 个月前
前言
好题,实在是一道很好的数学题。
本文主要参考了 这篇题解。
思路
看到这种题,特别是和因数相关,就可以往质数这一块多想想。
下面要证明一些定理。
引理 1:对于合数来说, 永远是满足条件的生成器。
证明:采用归纳法。
假设当前数为 ,小于 的合数都满足条件,那么可以分两种情况:
对于偶合数,有:,那显然也有 ,因此可以从 转移过来。 对于奇合数, 也一定可以表示成 的形式(其中 为最小的质因子)。因为 为合数,所以 (根据因数定理可知)。又因为 不为偶数,所以不含有偶数因子,那么 。所以, 也一定是一个合数。根据前置的条件, 可以被表示,而 是质数,所以 即 可以表示为 。因此能被表示。得证。
考虑完了合数的情况,再考虑一下质数。
引理 2:质数只能由本身来生成。
证明:反证法。
如果一个质数 可以由 生成而来(),那么一定有:,其中 并且 。因为 ,所以:。
且 。
是一个合数,矛盾。得证。
到这里就有一个整体的思路了。
- 序列中没有质数。根据 引理 1,直接输出 即可。
- 序列中有不同的质数。根据 引理 2,不管选择哪一个都不能满足所有的数,因此无解。
- 序列中有且只有一个质数。还要再讨论一下。
发现只能选这个质数,于是探讨一下选它满不满足其他的合数。
引理 3:对于偶合数 ,质数 能表示它必须满足 。
证明:考虑是否为充分必要条件。充分性:若 ,根据 引理 2 可知, 只能一步到达 。因为 ,所以。因此后面只要全用 就好了。必要性:若 ,因为 只有先到 ,而此时已经超过了 ,后面再操作只会变大,距离 越来越远,不可能表示出 。因此,该条件是充分必要条件,得证。
接着,考虑一下奇数的情况。
引理 4:对于奇合数 ,质数 能表示它必须满足 。其中 表示 的最小质因子。
证明:还是考虑充分必要条件。充分性:若 ,根据 引理 2 可知, 只能一步到达 。因为 为奇数,所以 也为奇数,所以 为偶数。根据 引理 3 可知是合法的。必要性:若 ,因为 只有先到 ,可知此时 ,因为奇偶性都不同。考虑能否到达 。假设一个数 可以一步到达 ,则跨越的数值 一定为 以及 的因数。可知此时 ,所以当 才满足条件。可是,矛盾。因此此时不可能到达 。所以该条件为充分必要条件,得证。
因此,只有一个质数的情况利用 引理3 以及 引理4 判断就好了。
代码
CPP#include<iostream>
using namespace std;
int t,n;
const int N=5e5+10;
bool v[N];
int p[N],cnt;
int num[N];
void prime(){
v[1]=1;
for(int i=2;i<N;i++){
if(!v[i]){
p[++cnt]=i;
}
for(int j=1;j<=cnt&&i*p[j]<N;j++){
int next=i*p[j];
v[next]=1;
if(next&1){
num[next]=next-p[j];
}else{
num[next]=next;
}
if(i%p[j]==0){
break;
}
}
}
}
int a[N];
int main(){
prime();
cin>>t;
while(t--){
scanf("%d",&n);
int x=0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(x==-1){
continue;
}
if(!v[a[i]]){
if(!x){
x=a[i];
}else{
x=-1;
}
}
}
if(x==-1){
puts("-1");
}else if(!x){
puts("2");
}else{
for(int i=1;i<=n;i++){
if(a[i]!=x&&num[a[i]]<2*x){
x=-1;
break;
}
}
cout<<x<<endl;
}
}
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...