Yes, Prime Minister(hdu7025)

原题链接

题目描述

在这里插入图片描述

输入描述

在这里插入图片描述

输出描述

在这里插入图片描述

输入样例

10
-2
-1
0
1
2
3
4
5
6
7

输出样例

6
4
3
2
1
1
2
1
2
1

题目大意:给定一个 x ,现需要找一个包含 x 的区间 [ l , r ] ,使得该区间内各元素之和为质数,求满足要求的区间的最小长度。

通过输入样例发现,给出的自然数的答案均为 1 or 2,即当前数为质数时长度为 1,当前数为约数时,可与前一位或后一位组成质数。因此不妨先通过打表验证该规律是否满足于所有自然数:

部分打表结果
可以发现1 ~ 30 的打表内即出现了不符合规律的 25、28,而通过计算也不难发现,25与前面 1 ~ 24 的任意一段区间之和都不能满足为素数的条件,即:25 + 24 , 25 + 24 + 23 , … ,25 + 24 + … + 1 间的任意一个组合都为约数。

此时感激万能群友提供的仅有区间长度小于等于 2 时,区间和才可能为质数的结论,证明如下:

当区间长度为 1 时,区间和即为 x ;
当区间长度为 2 时,区间和为 2 x + 1 ( 此处假定 x 为该区间内的最小数,下同 );
当区间长度为 3 时,区间和为 3 x + 3 ;
当区间长度为 4 时,区间和为 4 x + 6 ;
……

由于( 3 x + 3 )存在因子 3 ,( 4 x + 6 )存在因子 2 ,因此由该规律不难推出,仅当区间长度小于等于 2 时,区间和才可能为质数。所以对于自然数,可分为三种情况进行讨论:
①该数本身为质数,输出 1 即可;
②该数与相邻的前一位或后一位可组合成质数,输出 2 即可;
③以上两种条件均不符合,特殊处理。

而关于特殊处理的方式,我们可以通过 1 ~ 30 中的 25 和 28 进行讨论。由于区间长度不能大于 2 ,且当前数与前后位组成都不是质数,因此可以考虑将该自然数不断转化为 x + 1 ,直至转换后的数符合之前的 ① ② 条件中的一种。如:

对于 25,可使区间为 [ -25 , 26 ] ,则当前区间和为 26,而 26 可与 27 组合满足条件 ②,因此该样例的最终区间为 [ -25 , 27 ] ,长度为 25 * 2 + 3;

对于 28,可使区间为 [ -28 , 29 ] ,则当前区间和为 29,而 29 为质数满足条件 ①,因此该样例最终区间即为 [ -28 , 29 ] ,长度为 28 * 2 + 2;

而对于负数,可以直接映射到正数区间,即直接令 x = - x 并做以上的特殊处理即可。

参考代码

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 2e7+10;
typedef long long LL;
//线性筛
int vis[N], primes[N], cnt;
void _primes(int n){
    vis[0]=vis[1]=1;
    for(int i = 2; i < n; i++){
        if(!vis[i])primes[++cnt]=i;
        for(int j = 1; primes[j] <= n/i; j++){
            vis[primes[j]*i] = 1;
            if(i%primes[j]==0)break;
        }
    }
}

int x;
int main(){

    _primes(N);

    int T;
    scanf("%d",&T);
    while(T--){
     scanf("%d",&x);
        if(x>0 && !vis[x]){cout<<1<<endl;continue;}
        if(x>0 && !vis[x+x+1]){cout<<2<<endl;continue;}
        if(x>0 && !vis[x+x-1]){cout<<2<<endl;continue;}
        if(x<0)x=-x;
        for(int i = x+1; ;i++){
            if(!vis[i]){cout<<(i-1)*2+2<<endl;break;}
            else if(!vis[i+i+1]){cout<<(i-1)*2+3<<endl; break;}
        }
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值