2021“MINIEYE杯”中国大学生算法设计超级联赛(1)

HDU 7025. Yes, Prime Minister(南昌理工学院)


魔法阵.

题目介绍

Time Limit: 10000/10000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 332 Accepted Submission(s): 142

Problem Description
Mr. Hacker’s Department of Administrative Affairs (DAA) has infinite civil servants. Every integer is used as an id number by exactly one civil servant. Mr. Hacker is keen on reducing overmanning in civil service, so he will only keep people with consecutive id numbers in [l,r] and dismiss others.

However, permanent secretary Sir Humphrey’s id number is x and he cannot be kicked out so there must be l≤x≤r. Mr. Hacker wants to be Prime Minister so he demands that the sum of people’s id number ∑ri=li must be a prime number.

You, Bernard, need to make the reduction plan which meets the demands of both bosses. Otherwise, Mr. Hacker or Sir Humphrey will fire you.

Mr. Hacker would be happy to keep as few people as possible. Please calculate the minimum number of people left to meet their requirements.

A prime number p is an integer greater than 1 that has no positive integer divisors other than 1 and p.

Input
The first line contains an integer T(1≤T≤106) - the number of test cases. Then T test cases follow.

The first and only line of each test case contains one integer xi(−107≤xi≤107) - Sir Humphrey’s id number.

Output
For each test case, you need to output the minimal number of people kept if such a plan exists, output −1 otherwise.

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

Sample Output
6
4
3
2
1
1
2
1
2
1

解题思路

题目大意+(思路?):
——————选一段区间,区间内必须包括x,且区间和是一个素数,尽可能选取最小的区间,求区间长度,举个例子吧
比如第一样例 x = -2
我们为了保证区间和是一个素数的话,肯定都是正数对吧,那我就直接让负的部分直接抵消,区间就可以是 -2 -1 0 1 2,为了总和是素数,于是我们就延长变成了 -2 -1 0 1 2 3,所以答案为6
通过对样例的分析,我们可以发现 r > 0, r ≥ l,如果 l ≤ 0,此时 [l, r] 区间和 = [−l + 1, r] 的区间和,且 r ≥ −l + 1 > 0。
那就区间就是 l,l+1,l+2…r,之和为(r-l+1) * l + (r-l+1) * (r - l + 1 -1)
我们假设区间长度为1,2,—,可以发现
长度为1时:x,就是x,只要满足x时素数,即可
长度为2时:x,x+1 区间和为:x * 2+1
长度为3时:x,x+1,x+2 区间和为:3 * x+3,这必然不是一个素数
长度为4时:x,x+1,x+2,x+3 区间和为:3 * x+6,这也不是一个素数

我们可以发现满足和为素数的区间长度必然不长于 2。

我们先筛出2 × 10 e 7(+20)以内的素数 只要必要2 * 10 e 7略大的范围就可以了
如果在没有学过的话,嘿嘿,请看我的
博客.
当x > 0,我们首先判断这个数是否为素数,如果是素数 ,直接输出1,否之再判断这个数加上一数或者下一个是否为素数,是则输出2,那如果都不是怎么办,这就是特殊的地方了,结合之前的证明,长度不长于2,我们就要用到负数部分,将前面的数全部抵消,x变为x+1,举了例子吧!
x = 62 ,62+61=123 不是素数,62+63=125 不是素数,我们就将这个数给消去从63开始判断,区间变成了-62到62,这样就可以从0开始了,我们再重复x>0的判断就 0K了

同理x<0,我们将负数区间映射到正数区间,x = -x +1,判断这个数是否是素数,如果是素数 ,直接输出1,否之再判断这个数加下一个是否为素数,是则输出2,(不加上一个数,因为前面的都消去了),都不是的话,再次循环判断将区间长度+2,x++,为啥呢?举个例子吧!(有点怪怪的-----)
x = -3
我将其消去 ,区间为-3,-2,-1,0,1,2,3,我们再判断 x = -x+1 即 x = 4 是否为素数,很明显不是素数,而且4+5=9,也是不是 ,我们就就4也给消去,区间变为-4,-3,-2,-1,0,1,2,3,4,5是素数,所以长度为10

讲到这里我们就上代码吧


#include<iostream>
#include<algorithm>
using namespace std;
bool judge[20000010];//标记是否为素数
int primes[20000010];//存素数
int cnt = 0;
void getPrime0(int m) {//筛2到m内的素数
    for (int i = 2; i <= m; i++)
    {
        if (!judge[i]) primes[cnt++] = i;
        for (int j = 0; primes[j] <= m / i; j++)
        {
            judge[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
int main()
{
    int T, x, z;
    scanf("%d", &T);
    getPrime0(20000050);
    judge[1] = true;
    while (T--) {
        scanf("%d", &x);
        z = 0;//表示为区间长度
    start:; //循环判断
        if (x > 0) {
            if (judge[x] == 0) {//如果这个数是素数那区间长度就是1了
                printf("%d\n", 1 + z);
                continue;
            }
            if (judge[2 * x + 1] == 0 || judge[2 * x - 1] == 0)printf("%d\n", 2 + z);//如果这个数加上一数或者下一个数是素数的话就输出长度2+z
            else {//如果都不是的话,我们就将其全部消去,从下一个数判断
              z = x * 2 + 1; x++;
                goto start;
            }
        }
        else  {//如果是非正数的话,将其转化到正数区间,全部消去,x变为-x+1
            z = 1 - x * 2; x = -x + 1;
        start2:; //循环判断
            if (judge[x] == 0) {//如果消去的之后,x在取反的下一个位置后,这个数是素数,那么长度就是1+z了
                printf("%d\n", 1 + z); continue;
            }
            if (judge[2 * x + 1] == 0)printf("%d\n", 2 + z);//如果这个数不是话,我们不能一棒子打死,我们再看看这个数加上下一数是否为素数,那么长度就是2+z了
            else {//都不是的话,我们就将这个数消去,再从下一个位置判断
                z += 2, x++;
                goto start2;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值