Codeforces Round #618 (Div. 2)

Codeforces Round #618 (Div. 2)

A. Non-zero

题意

输入n个数,每次可以选定其中的一段数将其所有数+1,该操作可以执行若干次,求至少需要几次将所有数之和跟积都不为0

题解

先满足积不为0,直接统计出原本的0的个数,将其全部+1,然后再判断和是否为0,为0则任选一个数+1

代码

#include<iostream>
#include<cstdio>
using namespace std;
 
int main()
{   long N,i,sum,num,n,x;
    scanf("%ld",&N);
    while(N--){
        sum=num=0;
        scanf("%ld",&n);
        for(i=1;i<=n;i++){
            scanf("%ld",&x);
            sum+=x;
            if(!x)
                num++;
        }
        printf("%ld\n",num+((num+sum==0)?1:0));
    }
    return 0;
}

B. Assigning to Classes

题意

将2n个数分配到2个数列里,求这两个数列的中位数差值最小为多少

题解

直接对所有数进行排序,奇数下标的分到第一个数列,偶数下标的分到另一个数列,所以最小中位数差值为n+1下标和n下标数之差

代码

#include<cstdio>
#include<algorithm>
#define def 200010
using namespace std;
 
long a[def];
 
int main()
{   long N,n,i;
    scanf("%ld",&N);
    while(N--){
        scanf("%ld",&n);
        for(i=1;i<=2*n;i++)
            scanf("%ld",&a[i]);
        sort(a+1,a+2*n+1);
        printf("%ld\n",a[n+1]-a[n]);
    }
    return 0;
}

C. Anu Has a Function

题意

定义一个函数 f ( x , y ) = ( x ∣ y ) − y f(x,y)=(x|y)-y f(x,y)=(xy)y。给定n个数,求能使 f ( f ( . . . f ( f ( a 1 , a 2 ) , a 3 ) . . . ) , a n ) f(f(...f(f(a_1,a_2),a_3)...),a_n) f(f(...f(f(a1,a2),a3)...),an)最小的排列

题解

由于 ( x ∣ y ) − y = x − ( x & y ) (x|y)-y=x-(x\&y) (xy)y=x(x&y)
相当于二进制下x去掉与y相同的部分,所以, f ( f ( . . . f ( f ( a 1 , a 2 ) , a 3 ) , . . . ) , a n ) = a 1 − ( a 1 & ( a 2 ∣ a 3 ∣ . . . ∣ a n ) ) f(f(...f(f(a_1,a_2),a_3),...),a_n)=a_1-(a_1\&(a_2|a_3|...|a_n)) f(f(...f(f(a1,a2),a3),...),an)=a1(a1&(a2a3...an)),即对于第一个数的所有有1的位置,如果他是“独一无二”的,那就能够保留下来,而保留下来的就是 f ( . . . ) f(...) f(...)的结果
比如,
在这里插入图片描述
对于第一个数101110,所有的1为100000、1000、100和10,根据统计结果,独一无二的有100000和100,所以结果就是100100
第二个数001010的结果是000000
第三个数010011的结果是010001
比较结果可知,第一个数101110的结果是最大的

同时根据上面的式子,可以推断 f ( . . . ) f(...) f(...)的结果只与第一个数有关,与后面的数的排列无关,所以只用确定第一个数就好了

代码

#include<cstdio>
#include<algorithm>
#define def 100010
using namespace std;
 
long a[def],num[100];
 
int main()
{   long n,i,j,ans_q,maxx,q;
    scanf("%ld",&n);
    for(i=1;i<=n;i++){
        scanf("%ld",&a[i]);
        for(j=0;(1<<j)<=a[i];j++)
            if(a[i]&(1<<j))
                num[j]++;
    }
    ans_q=0;
    maxx=1;
    for(i=1;i<=n;i++){
        q=0;
        for(j=0;(1<<j)<=a[i];j++)
            if(num[j]==1&&(a[i]&(1<<j)))
                q|=1<<j;
        if(q>ans_q){
            maxx=i;
            ans_q=q;
        }
    }
    printf("%ld ",a[maxx]);
    for(i=1;i<=n;i++)
        if(maxx!=i)
            printf("%ld ",a[i]);
    printf("\n");
    return 0;
}

D. Aerodynamic

题意

给定一个凸多边形,将其所有顶点轮流移到原点,求移动轨迹的最外框形成的多边形与原多边形是否相似
在这里插入图片描述

题解

在移动的过程中,一个角的角度决定了最后形成的多边形的对角的角度,所以要使最后形成的图形与原来的相似,原图形就必须是中心对称图形,一遍循环判断即可

代码

#include<cstdio>
#include<set>
#define abs(i) (((i)>0)?(i):-(i))
#define def 100010
using namespace std;
 
struct node{
    double x,y;
    node(double x=0,double y=0){
        this->x=x;
        this->y=y;
    }
    friend bool operator <(node a,node b){
        if(a.x!=b.x)
            return a.x<b.x;
        else
            return a.y<b.y;
    }
}a[def],sum;
set<node>st;
 
int main()
{   long n,i;
    scanf("%ld",&n);
    for(i=1;i<=n;i++){
        scanf("%lf%lf",&a[i].x,&a[i].y);
        sum.x+=a[i].x;
        sum.y+=a[i].y;
    }
    sum.x/=n;
    sum.y/=n;
    for(i=1;i<=n;i++){
        auto now=st.find(node(-(a[i].x-sum.x),-(a[i].y-sum.y)));
        if(now==st.end())
            st.insert(node((a[i].x-sum.x),(a[i].y-sum.y)));
        else
            st.erase(now);
    }
    if(st.empty())
        printf("YES\n");
    else
        printf("NO\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值