Codeforces Round #618 (Div. 2)(ABC) 2020.02.09

A

题目

Guy-Manuel and Thomas have an array a of n integers [a1,a2,…,an]. In one step they can add 1 to any element of the array. Formally, in one step they can choose any integer index i (1≤i≤n) and do ai:=ai+1.

If either the sum or the product of all elements in the array is equal to zero, Guy-Manuel and Thomas do not mind to do this operation one more time.

What is the minimum number of steps they need to do to make both the sum and the product of all elements in the array different from zero? Formally, find the minimum number of steps to make a1+a2+ … +an≠0 and a1⋅a2⋅ … ⋅an≠0.

Input
Each test contains multiple test cases.

The first line contains the number of test cases t (1≤t≤103). The description of the test cases follows.

The first line of each test case contains an integer n (1≤n≤100) — the size of the array.

The second line of each test case contains n integers a1,a2,…,an (−100≤ai≤100) — elements of the array .

Output
For each test case, output the minimum number of steps required to make both sum and product of all elements in the array different from zero.

翻译

Guy-Manuel和Thomas有一个n个整数组成的数组[a1,a2,…,an]。在一个步骤中,它们可以向数组中的任何元素添加1。形式上,他们可以选择任意整数索引i(1≤i≤n)并执行ai:=ai+1。
如果数组中所有元素的和或积等于0,Guy-Manuel和Thomas不介意再做一次这个操作。
要使数组中所有元素的和和乘积都不等于零,至少需要多少步?正式,找到最小数量的步骤使a1 + a2 +……+≠0和a1⋅a2⋅…⋅≠0。

输入
每个测试包含多个测试用例。
第一行包含测试用例t的数量(1≤t≤103)。测试用例的描述如下。
每个测试用例的第一行包含一个整数n(1≤n≤100)——数组的大小。
每个测试用例的第二行包含n个整数a1,a2,…,an(−100≤ai≤100)——数组的元素。

输出
对于每个测试用例,输出使数组中所有元素的和和乘积都不同于零所需的最小步骤数。

例子

输入
4
3
2 -1 -1
4
-1 0 0 1
2
-1 2
3
0 -2 1
输出
1
2
0
2

大意

保证输入的一串数据中,无论相乘,还是相加,都不为零。
可以一次让其中一个数据+1,并计算所需的+1的次数。

思路

首先要确保无0,因为一但有0,相乘必然为0。
然后判断相加是否为0,若是为0,则次数+1,若不为0,就输出次数。

代码

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    int n;//数据个数
    cin >> n;
    while(n--)
    {
        int x;//单个数据的数量
        int a[1010];
        memset(a,0,sizeof(a));//因为是循环,所以要数组清零
        int i;
        cin >> x;

        for(i=0; i<x; i++)
        {
            cin >> a[i];
        }

        int f=0;//“+1”的次数
        for(i=0; i<x; i++)
        {
            if(a[i]==0)//判断是否为零
            {
                f=f+1;//次数+1
                a[i]=1;//数据+1
            }
        }
        int s=0;//数据之和
        for(i=0; i<x; i++)
        {
            s=s+a[i];
        }
        if(s==0)//判断数据之和是否为零
        {
            f=f+1;
        }
        cout << f <<endl;//输出
    }
    return 0;
}

B

题目

Reminder: the median of the array [a1,a2,…,a2k+1] of odd number of elements is defined as follows: let [b1,b2,…,b2k+1] be the elements of the array in the sorted order. Then median of this array is equal to bk+1.

There are 2n students, the i-th student has skill level ai. It’s not guaranteed that all skill levels are distinct.

Let’s define skill level of a class as the median of skill levels of students of the class.

As a principal of the school, you would like to assign each student to one of the 2 classes such that each class has odd number of students (not divisible by 2). The number of students in the classes may be equal or different, by your choice. Every student has to be assigned to exactly one class. Among such partitions, you want to choose one in which the absolute difference between skill levels of the classes is minimized.

What is the minimum possible absolute difference you can achieve?

Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). The description of the test cases follows.

The first line of each test case contains a single integer n (1≤n≤105) — the number of students halved.

The second line of each test case contains 2n integers a1,a2,…,a2n (1≤ai≤109) — skill levels of students.

It is guaranteed that the sum of n over all test cases does not exceed 105.

Output
For each test case, output a single integer, the minimum possible absolute difference between skill levels of two classes of odd sizes.

翻译

提示:奇数元素数组[a1,a2,…,a2k+1]的中位数定义如下:令[b1,b2,…,b2k+1]为排序后数组中的元素。然后这个数组的中位数等于bk+1。
有2n个学生,第i个学生有ai的技能水平。不能保证所有的技能水平都是不同的。
我们将一个班级的技能水平定义为该班级学生技能水平的中位数。
作为学校的校长,你可以把每个学生分配到两个班中的一个班,这样每个班的学生人数都是奇数(不能被2整除)。根据你的选择,每个班的学生人数可以是相同的,也可以是不同的。每个学生只能分到一个班。在这些分区中,您希望选择一个类的技能级别之间的绝对差异最小的分区。
你能达到的最小可能的绝对差异是多少。

输入
每个测试包含多个测试用例。第一行包含测试用例t的数量(1≤t≤104)。测试用例的描述如下。
每个测试用例的第一行包含一个整数n(1≤n≤105)——学生数量减半。
每个测试用例的第二行包含2n个整数a1,a2,…,a2n(1≤ai≤109)——学生的技能水平。
它保证所有测试用例的n的总和不超过105。

输出
对于每个测试用例,输出单个整数,即技能级别之间的最小可能绝对差异

例子

input
3
1
1 1
3
6 5 4 1 2 3
5
13 4 20 13 2 5 8 3 17 16

output
0
1
5

大意

共两组,输入的数据 x 是两组人数之和的一半,每组的人数必为奇数。
分别找出两组的中位数,保证两组中位数之差的绝对值最小。

思路

排序,取中间两个数字,两数相减即为答案。
因为需要每组为奇数,却没规定为几个。
若取前半段或后半段的连续数字,保证不了他们必为两组数的中位数。

代码

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

using namespace std;

int main()
{
    int n;
    cin >> n;//数据个数

    while(n--)
    {
        int x;
        int i;
        int d;//一个数据的总数量
        cin >> x;
        d=2*x;
        int y[1000000];
        memset(y,0,sizeof(y));//循环数据需清零

        for(i=1; i<=d; i++)
        {
            cin >> y[i];
        }

        sort(y+1,y+1+d);//直接排序

        int s;
        s=y[x+1]-y[x];//中位数相减
        cout << s <<endl;//记得转行
    }
    return 0;
}


C

题目

Anu has created her own function f: f(x,y)=(x|y)−y where | denotes the bitwise OR operation. For example, f(11,6)=(11|6)−6=15−6=9. It can be proved that for any nonnegative numbers x and y value of f(x,y) is also nonnegative.

She would like to research more about this function and has created multiple problems for herself. But she isn’t able to solve all of them and needs your help. Here is one of these problems.

A value of an array [a1,a2,…,an] is defined as f(f(…f(f(a1,a2),a3),…an−1),an) (see notes). You are given an array with not necessarily distinct elements. How should you reorder its elements so that the value of the array is maximal possible?

Input
The first line contains a single integer n (1≤n≤105).

The second line contains n integers a1,a2,…,an (0≤ai≤109). Elements of the array are not guaranteed to be different.

Output
Output n integers, the reordering of the array with maximum value. If there are multiple answers, print any.

翻译

Anu创建了自己的函数f: f(x,y)=(x|y)−y,其中|表示按位或运算。例如,f(11,6)= (11 | 6)−6 = 15 - 6 = 9。可以证明对于任何非负数x和y, f(x,y)的值也是非负的。
她想对这个功能做更多的研究,给自己带来了很多问题。但她不能解决所有的问题,需要你的帮助。这就是其中一个问题。
数组的值(a1, a2,…)被定义为f (f (f…(f a1, a2, a3),……一个−1),一个)(见笔记)。给你一个不一定有不同元素的数组。你应该如何重新排序它的元素,使数组的值是最大可能的?
输入
第一行包含一个整数n(1≤n≤105)。
第二行包含n个整数a1,a2,…,an(0≤ai≤109)。数组的元素不一定是不同的。
输出
输出n个整数,用最大值重新排序数组。如果有多个答案,请打印任何一个。

例子

input
4
4 0 11 6
output
11 6 4 0

input
1
13
output
13

大意

这个人用了 运算。
f(11,6)= (11 | 6)−6 = 15 - 6 = 9;
先将两个数字转化为二进制,进行运算,再将运算后的数字,与括号内的后一位数字相减。然后继续用结果接着运算。
不懂 或 运算的话,参考这位大大的结论吧:
数字逻辑电路中的逻辑运算法则–与、或、非、与非、或非、异或、同或

思路

由题意得,我们只要确定第一个数就好了。
将数字转化为二进制形式,高位补0,从头到尾遍历,判断那个数字的二进制高位首先为1,就ok了。剩下的随意排序。

代码

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

using namespace std;

int main()
{
    int n;//数字个数
    int i,j;
    int a[1000000];
    memset(a, 0, sizeof(a));//重置为0;

    cin >> n;
    for(i=0; i<n; i++)
    {
        cin >> a[i];
    }

    int f=0;//标记
    int x=0;//记录第一个数字
    int aaa;
    for(i=30; i>=0; i--)//从最高位开始遍历
    {
        for(j=0; j<n; j++)//从第一位数字开始遍历
        {
            if(a[j] & (1 << i))//取出 a[j] 在二进制下的第 i 位。若为1,条件为真,进入if从句
            {
                f++;
                x=j;
            }
        } 
        if(f==1)//结束循环
        {
            aaa=x;
            break;
        }
        
    }
    cout << a[aaa] ;//输出第一位
    for(j=0; j<n; j++)//剩下的随意输出
    {
        if(j!=aaa)
        {
            cout << ' ' << a[j];
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值