Educational Codeforces Round 104 (Rated for Div. 2)(A~E)

Solved


Solutions


A、Arena

题意:
\(n\) 个怪兽,第 \(i\) 个怪兽的攻击值为 \(a_{i}\),在其中任意挑选两个怪兽互相攻击,其中攻击值高的获胜且增加无限的攻击值,若平局则没有怪兽获胜,问有多少只怪兽可能最终获胜。
想法:
在所有怪兽中只有攻击值最小的不可能获胜,其他皆有可能。
代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=100005;

int main()
{
    int T,n;
    int a[105];
    cin>>T;
    while(T--){
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        int num=0;
        for(int i=1;i<=n;i++){
            if(a[i]!=a[1]){
                num=n-i+1;
                break;
            }
        }
        cout<<num<<endl;
    }
}

B、Cat Cycle

题意:
两只猫 \(A,B\) ,有长度为 \(n\) 的一个环, \(A\) 绕环逆时针走(即 \(n,n-1,...2,1,n,n-1,...\)\(B\) 绕环顺时针走(即 \(1,2,...n-1,n,1,2,...\),若 \(A,B\) 需要在同一点停留,则 \(B\) 需要让 \(A\),即 \(B\) 需要再向前走一格。问在第 \(K\) 时刻 \(B\) 停留在哪。
想法:

  • \(n\) 为偶数,两只猫不会冲突,那么答案就是正常绕环走的答案。
  • \(n\) 为奇数,两只会每隔 $\lfloor \frac{n}{2} \rfloor $ 时刻相遇,每次有这个间隔,即多走一步。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=100005;

int main()
{
    int T;
    ll n,k;
    cin>>T;
    while(T--){
        scanf("%lld%lld",&n,&k);
        ll num=n/2;
        if(n%2==0){
            ll pos=k%n;
            if(pos==0)pos=n;
            printf("%lld\n",pos);
        }else{
            ll d=(k-1)/num;
            ll pos=(k+d)%n;
            if(pos==0)pos=n;
            printf("%lld\n",pos);
        }

    }
}

C、Minimum Ties

题意:
\(n\) 支球队之间比赛,每两支球队之间进行一场比赛,若平局,则双方分数不变,否则胜者加 \(3\) 分,让每支球队的分数相同且平局最少,问比赛结果可以是怎么样。
想法:

  • 分奇偶讨论。
  • \(n\) 为奇数,那么每只球队将会对战偶数支球队,那么可以赢一半,输一半,如 \(5\) 支球队,即( \(1\) \(win\) \(2,3\)) ( \(2\) \(win\) \(3,4\)) (\(3\) \(win\) \(4,5\)) (\(4\) \(win\) \(5,1\)) (\(5\) \(win\) \(1,2\))正好每支球队赢 \(2\) 场,输 \(两场\)
  • \(n\) 为偶数,那么就是每支球队都平一场,然后就和奇数情况相同了。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=100005;

vector<int>v;
int main()
{
    int T;
    int n;
    cin>>T;
    while(T--){
        v.clear();
        scanf("%d",&n);
        if(n%2==1){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n-i;j++){
                  if(j>n/2){
                        v.push_back(-1);
                   }else{
                       v.push_back(1);
                   }
               }
            }
        }else{
            for(int i=1;i<=n;i++){
               for(int j=1;j<=n-i;j++){
                   if(j==n/2){
                       v.push_back(0);
                   }else if(j>n/2){
                        v.push_back(-1);
                   }else{
                       v.push_back(1);
                   }
               }
            }
        }
        int pos=v.size();
        for(int i=0;i<pos;i++){
            printf("%d%c",v[i]," \n"[i==pos-1]);
        }
    }
}

D、Pythagorean Triples

题意:
\(1\sim n\),中有多少组 \(a,b,c\) 满足 \(1\leqslant a\leqslant b\leqslant c\leqslant n\),且 \(c=a^2-b\),且 \(a,b,c\) 构成直角三角形, \(a,b\) 为直角边, \(c\) 为弦。
想法:

  • 综合上面的条件,推出 \(c^2=a^2+b^2\),结合 \(c=a^2-b\), 推出 \(c=b+1\)
  • 那么我们就对每个 \(a^2\) 考虑,也就是 \(a^2\) 为奇数时,会有一组出现。
  • 就可以打表出在每个 \(c\) 位置会出现一组。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=100005;

vector<int>v;
int main()
{
    int T;
    ll n;
    for(int i=3;i<=sqrt(2000000000);i++){
        ll num=i*i;
        if(num%2==0)continue;
        v.push_back(num/2+1);
    }
    cin>>T;
    while(T--){
      cin>>n;
      ll ans=0;
      for(int i=0;i<v.size();i++){
          if(v[i]<=n)ans++;
          else break;
      }
      cout<<ans<<endl;
    }
}

E、Cheap Dinner

题意:
题目给出 \(n_{1}\) 种第一道菜的花费, \(n_{2}\) 种第二道菜的花费, \(n_{3}\) 种饮料的花费, \(n_{4}\) 种甜点的花费。
给出 \(m_{1}\)\((x_{i},y_{i})\),表示编号为 \(x_{i}\) 的第一道菜和编号为 \(y_{i}\) 的第二道菜不能搭配。
给出 \(m_{2}\)\((x_{i},y_{i})\),表示编号为 \(x_{i}\) 的第二道菜和编号为 \(y_{i}\) 的饮料不能搭配。
给出 \(m_{3}\)\((x_{i},y_{i})\),表示编号为 \(x_{i}\) 的饮料和编号为 \(y_{i}\) 的甜点不能搭配。
问把四样东西搭配起来的最小花费是多少?

想法:

  • 我们可以首先考虑第二道菜中的每道菜与第一道菜搭配时的最小花费,得到 \(b_{i}\) 表示第 \(i\) 道第二道菜和所有第一道菜的搭配的最小花费。
  • 接下来用饮料去搭配 \(b_{i}\) 数组,然后就可以求出 \(c_{i}\) 表示第 \(i\) 种饮料和 \(b_{i}\) 的搭配的最小花费。
  • 最后用甜品去搭配 \(c_{i}\) 数组,答案就是得到的数组的最小值。
  • 那么对于每个 \(b_{i}\) 我们要求的就是 \(b_{i}+min(a_{j})\)(且 \(i\)\(j\) 可以搭配)
  • 那么我们可以在保存第一道菜的下标的前提下对第一道菜的花费进行排序,把每个不合法的搭配存入set容器,然后在对每个第二道菜通过二分查找当前最小值是否合法,在找到合法的最小值后break即可。
  • 因为不合法的搭配数量有限,可以保证时间复杂度不会是 \(O(n^2)\),而是接近于 \(O(nlogm)\)

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=200005;
const ll INF=1e18;

int n1,n2,n3,n4;
int m1,m2,m3;
struct node{
    ll val;
    int id;
    bool operator < (const node &x) const {
        return val<x.val;
    }
}a[maxn],b[maxn],c[maxn],d[maxn];
set<int>st1[maxn],st2[maxn],st3[maxn];
void input()
{
    scanf("%d%d%d%d",&n1,&n2,&n3,&n4);
    for(int i=1;i<=n1;i++){
        scanf("%lld",&a[i].val);
        a[i].id=i;
    }
    for(int i=1;i<=n2;i++){
        scanf("%lld",&b[i].val);
        b[i].id=i;
    }
    for(int i=1;i<=n3;i++){
        scanf("%lld",&c[i].val);
        c[i].id=i;
    }
    for(int i=1;i<=n4;i++){
        scanf("%lld",&d[i].val);
        d[i].id=i;
    }
    scanf("%d",&m1);
    for(int i=1;i<=m1;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        st1[y].insert(x);
    }
    scanf("%d",&m2);
    for(int i=1;i<=m2;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        st2[y].insert(x);
    }
    scanf("%d",&m3);
    for(int i=1;i<=m3;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        st3[y].insert(x);
    }
}
void solve()
{
    sort(a+1,a+n1+1);
    for(int i=1;i<=n2;i++){
        int flag=0;
        for(int j=1;j<=n1;j++){
            if(st1[i].find(a[j].id)==st1[i].end()){
                b[i].val=min(b[i].val+a[j].val,INF);
                flag=1;
                break;
            }
        }
        if(flag==0){
            b[i].val=INF;
        }
    }

    sort(b+1,b+n2+1);
    for(int i=1;i<=n3;i++){
        int flag=0;
        for(int j=1;j<=n2;j++){
            if(st2[i].find(b[j].id)==st2[i].end()){
                c[i].val=min(c[i].val+b[j].val,INF);
                flag=1;
                break;
            }
        }
        if(flag==0){
            c[i].val=INF;
        }
    }

    sort(c+1,c+n3+1);
    for(int i=1;i<=n4;i++){
        int flag=0;
        for(int j=1;j<=n3;j++){
            if(st3[i].find(c[j].id)==st3[i].end()){
                d[i].val=min(d[i].val+c[j].val,INF);
                flag=1;
                break;
            }
        }
        if(flag==0){
            d[i].val=INF;
        }
    }

    sort(d+1,d+n4+1);
    if(d[1].val==INF)d[1].val=-1;
    cout<<d[1].val<<endl;
}
int main()
{
    input();
    solve();
}
posted @ 2021-02-16 11:29  hachuochuo  阅读(130)  评论(0编辑  收藏  举报