Educational Codeforces Round 117 (Rated for Div. 2)

A. Distance

  • Distance
    题意:
    给定一个两个点A,B如要求点C,使得A到C的距离和C到B的距离是A到B的距离的一半,注意这里是曼哈顿距离,然后题目又有很多限制,构造一下C的位置就好了
    思路:
    直接在如果AB距离为奇数直接-1,否则就是沿着B点的水平方向或者竖直方向上一定可以找到一点成立。
    AC代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int x,y;
        scanf("%d%d",&x,&y);    
        if((x + y)&1)printf("-1 -1\n");
        else {
            int k = x + y;
            k /= 2;
            if(x -k >= 0)printf("%d %d\n",x-k,y);
            else printf("%d %d\n",x,y-k);
        }
    }
}

B. Special Permutation

题意:
给你一个长度为偶数的序列,然后再给你左边一般的最小值,和右边一半的最大值,让你构造一个n的排列,如果不能构造,输出-1

思路:
贪心的构造,左边把最大的往里放,右边把最小的往里放,然后判断一下数目够不够,注意左边不能放b,右边不能放a

#include <bits/stdc++.h>
using namespace std;
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n,a,b;
        scanf("%d%d%d",&n,&a,&b);
        vector<int>l,r;
        for(int i = n;i > a;i--){
            if(i!=b)l.push_back(i);
            if(l.size()==n/2-1)break;
        }
        l.push_back(a);
        for(int i = 1;i < b ;i++){
            if(i!=a)r.push_back(i);
            if(r.size()==n/2-1)break;
        }
        r.push_back(b);
        if(l.size()!=n/2||r.size()!=n/2)printf("-1\n");
        else {
            for(auto i : l){
                printf("%d ",i);
            }
            for(auto i : r){
                printf("%d ",i);
            }
            printf("\n");
        }
    }
}

C. Chat Ban

题意:
一个人要发一堆表情,最多发x个,然后问你最多发多少行

思路:
二分一个答案,然后等差数列求一下和,然后就很好判断是否能达到这个行数,注意他这个题目构造的行中的数目先上升在下降,所以要分两段求

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool ok(ll cur,ll k,ll x){
    ll ans = 0;
    if(cur > k){
        ans += (1LL + k) * k / 2;
        cur -= k;
        ans += (k - 1 + k - cur + 1)*(cur-1)/2;
        if(x > ans)return true;
        else return false ;
    }
    else {
        ans += (1 + cur - 1)*(cur - 1)/2;
        if(x > ans)return true;
        else return false ;
    }
    
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll k,x;
        scanf("%lld%lld",&k,&x);
        ll r = 2*k-1,l = 1;
        ll ans = 1;
        while(l<=r){
            ll mid = (l + r)>>1;
            if(ok(mid,k,x)){
                l = mid + 1;
                ans = max(ans,mid);
            }
            else r = mid - 1;
        }
        printf("%lld\n",ans);
    }
}

E. Messages

题意:
给你一个a,b,x,然后有两种替换法,把a换成|a - b|,或者把b换成|a-b|,问是否能把a或者b换成x这个数。
思路:
首先我们不妨设a > b,如果不是可以的调换,然后我们如果第一次操作把a ,b变为a, a - b,则第二次操作我们就不能减b的位置了,只能减a的位置a,那么第二次操作后会变成b,a-b,我们我们发现其实就是把大数a减了b,所以我们每次只考虑减大数直到大数减成小数。然后,我们只需要判断减的过程中是否出现把大数减成x的情况就是 a % b = = x % b a\%b==x\%b a%b==x%b(假设 a > b a > b a>b),然后就是注意一些特判条件,写一个类似辗转相除的写法。

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool f(ll a,ll b, ll c){
    if(a < b){
        swap(a,b);
    }
    if(a == c||b == c)return true;
    else if(a < c)return false;
    else if(b == 0)return false;
    else if(a % b == c % b)return true;
    else {
        return f(a%b,b,c);
    }
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll a,b,x;
        scanf("%lld%lld%lld",&a,&b,&x);
        if(a == x || b == x){
            printf("YES\n");
        }
        else if(a  < x && b < x){
            printf("NO\n");
        }
        else {
            if(a < b)swap(a,b);
            if(f(a,b,x)){
                printf("YES\n");
            }
            else printf("NO\n");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值