杭电多校总结2021-08-05

1001 Yes, Prime Minister

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.

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

在这里插入图片描述

如果不好理解的话,一位大佬的博客讲的十分详细
https://blog.csdn.net/laysan/article/details/119518351

#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;
}

1005 Median

Problem Description
Mr. docriz has n different integers 1,2,⋯,n. He wants to divide these
numbers into m disjoint sets so that the median of the j-th set is bj.
Please help him determine whether it is possible.

Note: For a set of size k, sort the elements in it as c1,c2,⋯,ck, the
median of this set is defined as c⌊(k+1)/2⌋.

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

The first line of each test case contains 2 integers n,m(1≤m≤n≤105) -
the number of integers that Mr. docriz has, and the number of sets he
want to divide these numbers into.

The next line contains m integers b1,b2,⋯,bm(1≤bi≤n). It is guaranteed
that all the numbers in b are distinct.

It is guaranteed that ∑n≤2×106.

Output
For each test case, output "YES’’ if it is possible to achieve his goal, or "NO’’ otherwise.

大意:
1到n的序列要求分割成m段,每一段的中位数为给定的 b i 。此处中位数定义与正常定义不同,偶数个时为中间偏左的数。给定 m 个中位数 b i ,问能否有一种合适的划分。
显然b1, b2, · · · , bm 这m 个数要放在m 个不同的集合中,剩下的n − m 个数字要放到这m 个集合里且不影响每
个集合的中位数。使用一个例子以方便说明:假设n = 6,m = 2, b1 = 3, b2 = 5,那么1, 2, · · · , n 这些数会被b 分
成1, 2、4、6 这三段,且任意两段中的任意一对数字可以配对消掉。所以最后剩下的所有数字一定是同一段内的。
因此讨论两种情况:
• 如果长度最大的段的数字个数不大于其它段的数字个数之和,那么最终要么全部消掉,要么剩下一个,且剩
下的这个数可以在任何一段内。如果会剩下,不妨将最后一段的数字剩下一个,此时再把最后一段的数字放
到中位数最小的集合中即可满足题意,所以答案为YES。
• 如果长度最大的段的数字个数大于其它段的数字个数之和,那么最终剩下的所有数字都在最大的这段内。设
中位数小于这一段的最小值的集合的个数为x,容易发现当且仅当x 不小于这一段剩下的数字个数时有解。

#include <cstdio>
#include <algorithm>
using namespace std;
int b[100005];
int main()
{
    int t, n, m;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m;i++)
            scanf("%d", &b[i]);
        sort(b + 1, b + m + 1);
        b[m + 1] = n + 1;
        bool flag = 0;
        for (int i = 1; i <= m + 1;i++)
            if (2 * (b[i] - b[i - 1] - 1) > i - 1 + n - m)
            //2*(b[i]-b[i-1]-1) 为完全匹配所需要的数(含自己)。
            //i-1是左侧中位数个数。n-m为全域待分配的数
            {
                flag = 1;
                break;
            }
        if(flag)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值