CF-Good Bye 2019比赛总结

A:Card Game
题意:
给出两组卡片,问最后谁能按照游戏规则拿到全部的卡片。

解题思路:
可以得出谁的卡片最大谁就能拿到全部的。

代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e6+10;
const int mod=998244353;
int n,m,k,T,t,sum,q,c,d;
int a[110];
void solve(){
    scanf("%d%d%d",&n,&m,&k);
    c=d=0;
    for(int i=0;i<m;i++)scanf("%d",&t),c=max(c,t);
    for(int i=0;i<k;i++)scanf("%d",&t),d=max(d,t);
    if(c>d)printf("YES\n");
    else printf("NO\n");
}
int main(){
    scanf("%d",&T);
    while(T--){
        solve();
    }
    return 0;
}

B:Interesting Subarray
题意:
给出一段数组,让你找到一个区间,使得该区间的最大值减去最小值大于等于区间长度,并输出这个区间。

解题思路:
若存在这样的区间,那么一定存在相邻的的两个数之差大于等于2,因为如果不存在这样的区间,只能是相邻两个数加1、0,-1的序列。所以只需要找到这两个数输出下标即可。

代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e6+10;
const int mod=998244353;
int n,m,k,T,t,sum;
int a[N],b[N];
void solve(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        b[i]=a[i]-a[i-1];
    }
    for(int i=2;i<=n;i++){
        if(abs(b[i])<=1)continue;
        else{
            printf("YES\n%d %d\n",i-1,i);
            return;
        }
    }
    printf("NO\n");
}
int main(){
    scanf("%d",&T);
    while(T--){
        solve();
    }
    return 0;
}

C:Make Good
题意:
给出一个序列,让你添加0到3个数字,使得所有数之和等于所有数字异或和的2倍。

解题思路:
首先先将异或和变为0,即加上原来所有数字的异或和,然后再加上当前所有数的总和即可。

代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e6+10;
const int mod=998244353;
LL n,m,k,T,t,sum,now;
int a[N],b[N];
void solve(){
    sum=now=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%lld",&k),sum+=k,now^=k;
    printf("2\n");
    printf("%lld ",now);
    sum+=(now);
    printf("%lld \n",sum);
}
int main(){
    scanf("%d",&T);
    while(T--){
        solve();
    }
    return 0;
}

D:Strange Device
题意:
交互题,给出n,k,你可以最多询问n次序列,每一次询问k个数字,机器会给你这k个数字中的第m小的数字的下标和数值,问结果m是多少。

解题思路:
询问k+1次,每一次询问1到k+1中的k个数字,结果就是给出交互结果中最大值出现的次数。

代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e5+10;
const int mod=10000007;
int n,m,k,T,t,ans,y,x;
int a[N];
void solve(){
    scanf("%d%d",&n,&k);
    map<int,int>mp;
    for(int i=1;i<=k+1;i++){
        printf("?");
        for(int j=1;j<=k+1;j++){
            if(j!=i)printf("% d",j);
        }
        printf("\n");
        fflush(stdout);
        scanf("%d%d",&x,&y);
        mp[y]++;
        ans=max(ans,y);
    }
    printf("! %d\n",mp[ans]);
}
int main(){
    solve();
    return 0;
}

E:Divide Points

题意:
给出n个不同的点,你要把它们分成两组,使得任意不同组之间的欧拉距离与同组之间的欧拉距离不同。

解题思路:
首先按在坐标(x,y)的奇偶性将所有点划分到4个桶:00,01,10,11;1代表奇数,0代表偶数。

在一个桶内的距离一定是偶数,在不同桶但异或起来等于11的距离也是偶数(如00和11,10和01),其它的都是奇数。

若只有一个桶有点,把所有的坐标除以2,然后重复划分过程。
把一个桶内的所有点的x,y除以2,所有点间距离刚好缩短两倍(同一个桶内的点的下标差值一定是偶数,可以整除2,距离一定是刚好缩短两倍),不会影响判断结果。除2以后点的奇偶性将发生改变,然后重复这个过程。

若至少两个桶内有点:
任意两个桶间的距离和桶内的距离都不会相等:
若两个桶异或不为11,那么桶间的距离是奇数,桶内是偶数。若两个桶异或为11,桶内的距离是两个偶数的平方相加,其和一定是4的倍数,桶间的距离是两个奇数的平方相加,其和是2的倍数但不是4的倍数。
若 00 和 11的点的个数和 大于 0 且 10 和 01 的点的个数和 大于 0,则将00 和 11 分一组,10 和 01分一组。

否则直接输出一个桶的点

代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=1e5+10;
const int mod=10000007;
int n,m,k,T,t,ans;
int cnt[2][2];
struct node{
    int x,y;
}q[N];
void solve(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&q[i].x,&q[i].y);
        q[i].x+=1e6;
        q[i].y+=1e6;
    }
    while(true){
        for(int i=1;i<=n;i++)cnt[q[i].x%2][q[i].y%2]++;
        if(cnt[0][0]+cnt[1][1]>0&&cnt[0][1]+cnt[1][0]>0){//优先判断(0,0)和(1,1)的情况
            printf("%d\n",cnt[0][0]+cnt[1][1]);
            for(int i=1;i<=n;i++){
                if(q[i].x%2==q[i].y%2)printf("%d ",i);
            }
            return;
        }
        if(cnt[0][1]+cnt[0][0]>0&&cnt[1][1]+cnt[1][0]>0){
            printf("%d\n",cnt[0][1]+cnt[0][0]);
            for(int i=1;i<=n;i++){
                if((q[i].x%2==0&&q[i].y%2==1)||(q[i].x%2==0&&q[i].y%2==0))
                printf("%d ",i);
            }
            return;
        }
        for(int i=1;i<=n;i++)q[i].x/=2,q[i].y/=2;
        cnt[0][0]=cnt[0][1]=cnt[1][0]=cnt[1][1]=0;
    }
}
int main(){
    solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值