Educational Codeforces Round 117 (Rated for Div. 2) ABCDE

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 117 (Rated for Div. 2) ABCDE相关的知识,希望对你有一定的参考价值。

A

题意:

  • 给出A坐标(0,0)和B坐标,d表示两点横纵坐标绝对值之和。
  • 求是否存在C(x,y)满足d(A,C)=d(B,C)=d(A,B)/2,不存在就-1.

思路:

  • d(A,B)直接已知,如果是个奇数就-1。
  • 因为A是00,所以C坐标x+y直接已知,然后枚举C的x和y,代入计算d(B,C)是否满足条件即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;

int main()
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T;  cin>>T;
    while(T--)
        int xb, yb;  cin>>xb>>yb;
        int dab = xb+yb;
        if(dab%2==1)
            cout<<"-1 -1\\n";
            continue;
        
        int d = dab/2, ok = 1;
        for(int i = 0; i <= d; i++)
            int j = d-i;
            int x = abs(i-xb)+abs(j-yb);
            if(x==d)
                cout<<i<<" "<<j<<"\\n";
                ok = 0;
                break;
            
        
        if(ok==1)
            cout<<"-1 -1\\n";
            continue;
        
    
    return 0;


B

题意:

  • 给出n,a, b,判断是否存在长度为2n的排列。
  • 满足左半边的所有元素的最小值等于 a,右半边的所有元素中的最大值等于 b。

思路:

  • 左边n个中,先放个a,然后从2n往小的枚举,不是b就填上。右边放个b,从1往大的枚举。
  • 如果从大到小或从小到大放的过程中遇到了自己,即数字不够用了,那么就-1。放完了就输出。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
int v[maxn];
int main()
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T;  cin>>T;
    while(T--)
        int n, a, b;  cin>>n>>a>>b;
        int ok = 1;
        v[1] = a;
        int cur = 1;
        int cnt = 0;
        for(int i = n; i >= 1; i--)
            if(cnt==n/2-1)break;
            if(i!=b)
                v[++cur] = i;
                cnt++;
            
            if(i==a)
                ok = 0; break;
            
        
        cnt = 0;
        cur = n/2+1;
        v[cur] = b;
        for(int i = 1; i <= n; i++)
            if(cnt==n/2-1)break;
            if(i!=a)
                v[++cur] = i;
                cnt++;
            
            if(i==b)
                ok = 0;break;
            
        
        if(ok==0)
            cout<<"-1\\n";  continue;
        
        for(int i = 1; i <= n; i++)
            cout<<v[i]<<" ";
        
        cout<<"\\n";
    
    return 0;


C

题意:

  • 给出k,你需要发送最多2k-1条消息,每条消息分别包含1->k,k->1个表情。
  • 你一共可以发送x个表情,求你最多可以发送多少条消息(没打完也算一条)

思路:

  • 表情和消息的关系是,等差数列求和。设发了i条消息,则表情数sum可以计算。
    i<=k sum =(1+i)*i/2 < x
    i>=k sum = (1+k)*k/2+(sum2) , sum2 = (k-1+j)*(k-j)/2 < x,j=i-k
  • 令总数sum=x作为边界,反向可以算出消息条数i,暴力一下附近的几个数可以避免对边界的讨论。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
int main()
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T;  cin>>T;
    while(T--)
        LL k, x;  cin>>k>>x;
        LL all = k*(k-1)+k, haf = (1+k)*k/2;
        if(all < x) cout<<2*k-1<<"\\n"; continue;
        LL i = (LL)(sqrt(x*2)-1);
        if(x <= haf)
            LL now = (1+i)*i/2;
            while(now < x)
                i++;
                now += i;
            
            cout<<i<<"\\n";
        else
            //cout<<"tmp"<<"\\n";
            x -= haf;
            LL i = (LL)(sqrt((k+1)*(k+1)-2*x)-1);
            LL cnt = k-i;
            LL now = (k-1+i)*(k-i)/2;
            // cout<<"now"<<now<<" "<<cnt<<"\\n";
            while(now < x)
                i--;
                cnt++;
                now += i;
            
            cout<<k+cnt<<"\\n";
        
    
    return 0;


D、

题意:

  • 给出数对(a,b)和x,每次可以令a=|a-b|或者b=|a-b|,判断能否若干次操作后得到x。

思路:

  • 每次都|a-b|不难想到gcd和辗转相除法,所以可以按照gcd的方式递归下去。
  • 如果过程中出现了(a-x)%b==0,即a和x同余b,那就可以不断的用a减去b直到获得x,此时返回true,否则若最后除完了也得不到,那就得不到了。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
bool check(LL a, LL b, LL x)
    if(!b)return a==x;
    if(x<=a && (a-x)%b==0)return 1;
    return check(b,a%b,x);

int main()
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T;  cin>>T;
    while(T--)
        LL a, b, x;  cin>>a>>b>>x;
        if(a < b)swap(a,b);
        if(check(a,b,x))cout<<"YES\\n";
        else cout<<"NO\\n";
    
    return 0;


E、

题意:

  • n个学生,每个学生需要阅读到消息mi,但是他最多只会阅读ki条消息。
  • 老师可以固定?条消息,然后学生阅读到mi的概率为 min(ki, ?)/?。
  • 求老师固定哪些消息,可以让学生阅读到需要阅读的消息的总期望值最大。

思路:

  • 因为k<=20, mi <= 2e5,所以可以直接暴力枚举需要固定的消息条数i。
  • 然后暴力每个学生需要阅读的消息对期望的贡献,即消息m[j]对应的贡献a[m[j]] += min(k[j],i),按照贡献对这两万条消息从大到小排序,取最大的前i条,更新答案即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5+2000;
int m[maxn], k[maxn];
pair<int,int>a[maxn];
int main()
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int n;  cin>>n;
    for(int i = 1; i <= n; i++)cin>>m[i]>>k[i];
    LL x = 0, y = 1;
    vector<int>ans;
    for(int i = 1; i <= 20; i++) //暴力贴i条消息
        for(int j = 1; j <= 200000; j++)a[j] = 0,j; //暴力消息mi=j
        for(int j = 1; j <= n; j++)a[m[j]].first += min(k[j], i);
        sort(a+1,a+200000+1);
        reverse(a+1,a+200000+1);
        LL s = 0;
        for(int j = 1;  j<= i; j++) s+=a[j].first; //取最大的i条
        if(x*i < y*s)
            x = s; y = i;
            ans.clear();
            for(int j = 1; j <= i; j++)
                ans.push_back(a[j].second);
            
        
    
    cout<<ans.size()<<"\\n";
    for(int x : ans)cout<<x<<" ";
    return 0;


以上是关于Educational Codeforces Round 117 (Rated for Div. 2) ABCDE的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27