CodeChef Starters 146 Division 4 A~E

打着玩的 写了五题懒得写了 再加上是div4 所以都是完全初学者级别的题目 小灯们可以来试试(
七夕快乐 队友出去陪女友 我晚上还要打苦工用他号打Div2 直接给他WA个1314发祝福一下他们吧(
今天的封面来自轻小说《被诅咒的纯爱》 是的七夕节就该看这种很甜的小说

A - Olympics 2024

题意

奥运会到了,某国家代表队现在有 G G G枚金牌, S S S枚银牌, B B B枚铜牌,问想要达成金银铜各有5枚的目标至少还需要打多少场比赛?

思路

因为我们要的是最少的情况,那就假设完全吹黑哨,想要啥牌就有啥牌,已经超过5枚的自然不需要管了,而不到5枚的,直接用5减去现在有的奖牌个数即可

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int G,S,B;
    scanf("%d%d%d",&G,&S,&B);
    int ans=0;
    if(G<5) ans+=5-G;
    if(S<5) ans+=5-S;
    if(B<5) ans+=5-B;
    printf("%d\n",ans);
}

int main()
{
    int T=1;
    //scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

B - No Winner

题意

现在有三个人分别已经获得了 A A A B B B C C C场胜利,现在还可以安排 M M M场比赛,问有没有机会让他们之间的两个人最终分数相同

思路

我们先把他们现在的胜场数排一个序,因为肯定是离得最近的两个人想把比分追平最简单,三个人就有两个分叉,只要还能安排的场次比其中一个大,那么我们就可以先让两个人打平,然后剩下那个人之后就一直让他赢就可以了

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int a,b,c,m;
    scanf("%d%d%d%d",&a,&b,&c,&m);
    //sort a,b,c;
    if(a>b)
    {
        swap(a,b);
    }
    if(a>c)
    {
        swap(a,c);
    }
    if(b>c)
    {
        swap(b,c);
    }
    int ned=min(abs(a-b),abs(b-c));
    if(m>=ned)
    {
        printf("YES\n");
    }
    else
    {
        printf("NO\n");
    }
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

C - Knockout tournament

题意

现在16个人去打一系列的锦标赛,锦标赛就是这个样子的
在这里插入图片描述
现在已知这16个人的能力值,假设比赛不会出现任何爆冷,也就是说能力值高的一定能击败能力值低的,问每个人最多可以赢多少局

思路

对于每个人而言,他赢肯定是赢能力值比他低的,第一轮想赢那么至少要有一个能力值比他低的,到了第二轮还想赢,那么除了第一轮赢的那个,他必须保证他的对手和他对手在第一轮击败的那个人都得能力值比他低,以此类推。也就是说我每想多赢一局比赛,我就要多 2 i 2^i 2i个能力值比我低的人给我霍霍。所以我们需要统计每个人比多少人能力值高,然后再看这些人能在 1 + 2 + 4 + 8 + 16... 1+2+4+8+16... 1+2+4+8+16...的攻势下支撑多少轮

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
int pre[5]={1,3,7,15,31};

void solve()
{
    int a[16];
    for(int i=0;i<16;i++)
        scanf("%d",&a[i]);
    int less[16];
    memset(less,0,sizeof(less));
    for(int i=0;i<16;i++)
    {
        for(int j=0;j<16;j++)
        {
            if(i!=j && a[j]<=a[i])
            {
                less[i]++;
            }
        }
    }
//    for(int i=0;i<16;i++)
//    {
//        printf("%d ", less[i]);
//    }
//    printf("\n");
    int ans[16];
    memset(ans,0,sizeof(ans));
    for(int i=0;i<16;i++)
    {
        int cnt=0;
        for(int j=0;j<5;j++)
        {
            if(less[i]>=pre[j])
                cnt++;
        }
        ans[i]=cnt;
    }
    for(int i=0;i<16;i++)
    {
        printf("%d ", ans[i]);
    }
    printf("\n");
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

D - Permutation Construction

题意

构造一个长度为n的排列(即1~n都只出现一次但顺序不固定的数组),满足对于2到N-1的所有 i i i都满足 P i ≥ ( P i + 1 − P i − 1 ) 2 P_i \geq (P_{i+1}-P_{i-1})^2 Pi(Pi+1Pi1)2

思路

构造题,我们需要的是每次 P i + 1 P_{i+1} Pi+1 P i − 1 P_{i-1} Pi1都尽量小,所以我们可以分别填,先填奇数位为 1 , 2 , 3... 1,2,3... 1,2,3...填到最后一格之后再把剩下的数填到偶数位上就可以了

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int n;
    scanf("%d",&n);
    if(n==1) cout<<"1\n";
    else if(n==2) cout<<"1 2\n";
    else
    {
        int hlf=n/2;
        if(n%2==1) hlf++;
        for(int i=1;i<=n/2;i++)
        {
            printf("%d %d ",i,hlf+i);
        }
        if(n%2==1) printf("%d ",hlf);
        printf("\n");
    }
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

E - Bouncing Ball

题意

给你一个数组,表示这个位置的墙的高度,你现在可以在任何初始高度为0的空地放一个球,并选择它往左边或者右边弹,每次撞到墙就会让墙的高度减1并且往另外一个方向反弹,问有多少种放法可以在最后使得所有墙都被拆干净

思路

不妨考虑几个最基础的情况,最好想的一定就是1 0 1,这样的话放在中间的空地往左往右都可以消除干净,那么进一步我们就可以看出1 1 0 2其实也可以,也就是说左边墙的总高度等于右边就行,因为分左右,所以算作两种放法
但是还没有结束,我们发现1 0 2这样的情况,如果初始是往右推的话也可以清除干净,与上面相同,也就是左边和右边墙总高度的差值的绝对值等于1也可以贡献一种放法
然后左右的总高度我们使用前缀和和后缀和提前维护一下就可以了,具体而言,因为每次都计算一下左边所有墙的高度在最坏情况下计算太慢了,我们可以提前算好每一个位置左边和右边的抢的总高度提前存起来,需要的时候再用就行了

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int n;
    scanf("%d",&n);
    int a[n+1];
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    ll pre[n+1],bak[n+1];
    pre[0]=0;
    for(int i=1;i<=n;i++)
    {
        pre[i]=pre[i-1]+a[i];
    }
    bak[n+1]=0;
    for(int i=n;i>=1;i--)
    {
        bak[i]=bak[i+1]+a[i];
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==0)
        {
            if (abs(pre[i - 1] - bak[i + 1]) == 1)
            {
                ans++;
            }
            else if (abs(pre[i - 1] - bak[i + 1]) == 0)
            {
                ans += 2;
            }
        }
    }
    printf("%d\n",ans);
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值