牛客练习赛92

比赛地址

第一题

题目大意:
给三个数N,A,B,需要构造一个长度为N的数组,保证中位数为A,平均数为B;保证数组中的数在[-10^{12}, 10^{12}]

解题:

  • 数组全部设置为A
  • 经过上面操作,所有数之和为n * a
  • 比较n * bn * a,大于就给a[n - 1] += n * b - n * a;小于就给a[0] -= n * a - n * b(范围是不会超的)

NOTE:

  • 数据的问题,用long long
点击查看代码
#include<iostream>
#include<cstring>
using namespace std;

typedef long long LL;
const int N = 1e5 + 10;

LL a, b, n, q[N];

int main(){
    scanf("%ld%lld%lld", &n, &a, &b);
    
    for(int i = 0; i < n; ++i) q[i] = a;   
    if(n * b >= n * a) q[n - 1] += n * b - n * a;
    else q[0] -= n * a - n * b;
    
    for(int i = 0; i < n; ++i) printf("%lld ", q[i]);
    return 0;
}

第二题

题目大意:
给n(表示数组大小),k(分块的数量),a[];要求分成k块,并且每一块的和不为0,不存在符合条件的返回NO

解题:

  • 特判处理:①k==1时,所有和为0,返回NO,反之;②非零数的数量小于k的值,返回NO,反之可得---2<=如果非零数的数量<=k必有解
  • 将数据分成三块,分别为负数,正数,0
  • 先将负数,正数排序,从小到大,将每一个看成单独的段,输出k-2个,留2后面操作处理
  • 剩下两个段:第一个存储负数,第二个存储正数,0随便放,不影响

NOTE:

  • 在求所有数之和时,注意数据大小1e5 * 1e9 = 1e14 > int,会爆int,所以需要用long long
点击查看代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 1e5 + 10;

int n, k, a[N], nz[N], t[N];

int main(){
    scanf("%d%d", &n, &k);
    if(k == 1){
        long long sum = 0;
        for(int i = 0; i < n; ++i){
            scanf("%d", &a[i]);
            sum += a[i];
        }
        if(!sum) printf("NO");
        else{
            printf("YES\n%d ", n);
            for(int i = 0; i < n; ++i) printf("%d ", a[i]);
        }
    }
    else{
        int nz_num = 0;
        for(int i = 0; i < n; ++i){
            scanf("%d", &a[i]);
            if(a[i]){
                nz[nz_num ++] = a[i];
            }
        }
        
        if(nz_num < k) printf("NO");
        else{
            printf("YES\n");
            sort(nz, nz + nz_num);
            for(int i = 0; i < k - 2; ++i) printf("1 %d\n", nz[i]);
            
            // 输出第一个
            int f_num = 0;
            if(nz[k - 2] < 0){
                for(int i = k - 2; i < n - 1; ++i){
                    if(nz[i] < 0) t[f_num ++] = nz[i];
                    else break;
                }
                printf("%d ", f_num);
                for(int i = 0; i < f_num; ++i) printf("%d ", t[i]);
            }
            else{
                printf("1 %d", nz[k - 2]);
            }
            puts("");
            // 输出第二个
            if(f_num > 0){
                printf("%d ", n - f_num - k + 2);
                for(int i = 0; i < n - nz_num; ++i) printf("0 ");
                for(int i = f_num + k - 2; i < nz_num; ++i) printf("%d ", nz[i]);
            }
            else{
                printf("%d ", n - k + 1);
                for(int i = 0; i < n - nz_num; ++i) printf("0 ");
                for(int i = k - 1; i < nz_num; ++i) printf("%d ", nz[i]);
            }
        }
    }
    return 0;
}

第三题

题目大意:
给n个点,给定一个a条边和b条边的图,如果两个图存在相同的边即有关联,反之;需要求有多少种有关联的情况

解题:

  • 正向思考难度大,则反向思考,求没有关联的情况
  • 总情况为\(C_{m}^{a} * C_{m}^{b}\)(m是总边数),无关联的情况\(C_{m}^{a} * C_{m - a}^{b}\)(先给第一个图分配a条边,再从剩下的边中选b条给第二个图)
  • ans = 二者之差
    b
    代码后面再补
posted @ 2021-11-27 15:03  KJGL  阅读(47)  评论(0)    收藏  举报