2023年新生周赛(第三周)题解

        作为2022级学姐,这次也是第一次出题,题目出的也会有许多的不足,还请见谅。相对来说这次出题目时觉得的难度并不是很大,在大家写的过程中感觉还是出难了一点,D题相对来说时间卡的有点严重,其余的AF会相对来说会偏难一点,其次是EHG,BC是简单点的。下面就是各个题目的分析以及答案。

A题(糖果之“战”)

       两个人轮流拿,不能拿与上一个人拿的一样的,其实意思就相当于一个人去拿这些糖果,每次拿最多的那一堆的一个,不能连续拿同一种。其实判断能不能也很简单。

        如果结果是能,那就说明1.要么有且只有一种,并且这一种只有一个糖果;2.最多的糖果的种类有多个,可以几种换着拿,一直拿到与剩下几种中数量多那个一样,然后接着轮流拿,直到结束;3.第一次拿完最多的之后,回到第二种情况。

        否则就是不能。

        总结来说就是,只要n==1并且a[0]==1;或者从大到小排序之后a[0]-a[1]<=1,结果就是YES,否则为NO。

        但是要注意排序方法,否则将超时哦。

#include <stdio.h>
int main()
{
    int t,i,n,a[200005];
    scanf("%d",&t);
    while(t>0)
    {
        t--;
        int max=0,maxs=0,v;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);//输入
            if(a[i]>max)
            {
                max=a[i];
                v=i;
            }//记录最多的糖果的数量,以及是第几种
        }
        if(n==1)
        {
            if(a[0]>1)
            {
                printf("NO\n");
            }
            else
            {
                printf("YES\n");
            }
        }//一种的特殊情况;
        else
        {
            for(i=0;i<n;i++)
            {
                if(a[i]>maxs&&i!=v)
                {
                    maxs=a[i];
                }
            }//大于1种时,找到第二多的糖果数量,这也就是为什么上面找最多的时候记录它是第几种的原因;
            if(max-maxs>1)
            {
                printf("NO\n");
            }
            else
            {
                printf("YES\n");
            }
        }
    } 
    return 0;
}//c
#include<bits/stdc++.h>
using namespace std;
int t,n,a[999999];
int main()
{
    cin>>t;
    while(t--&&cin>>n)
    {
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+n+1),puts(a[n]-a[n-1]>1?"NO":"YES");
    }
}//c++

B题(简单统计数字)

        这个题目也算是一道签到题了。注意的是按降序,其次不超过1000位的整数,所以长整型也不能满足要求,直接使用字符串,以回车结束,另外再用一个数组,用出现的数字(1~9)作为下标,值来统计出现的次数。

#include <stdio.h>
#include <string.h>
int main()
{
    char c[1001];
    int a[10]={0};
    scanf("%s",c);
    int l;
    l=strlen(c);
    int i;
    for(i=0;i<l;i++)
    {
        a[c[i]-'0']++;
    }
    for(i=9;i>=0;i--)
    {
        if(a[i]>0)
        {
            printf("%d:%d\n",i,a[i]);
        }
    }
    return 0;
}

C题(奖学金)

        真签到题。

        输入四科成绩,题目意思就是只要有一科成绩小于60,卷卷就不能申请奖学金。

#include <stdio.h>
int main()
{
    int a,b,c,d;
    scanf("%d %d %d %d",&a,&b,&c,&d);
    if(a<60||b<60||c<60||d<60)
    {
        printf("Next refueling!");
    }
    else
    {
        printf("It's possible!");
    }
    return 0;
}

D题(派蒙爱吃素)

        显而易见只有当a为1且b为素数,或者b为1且a为素数时才为素数。时间卡的有点厉害所以正确率也不是很高,其实只要把偶数跳过去就可以。

        注意:有些同学是将a与b相乘之后再去判断是否为素数,可以过,但是在判断时要多加条件

#include<stdio.h>
#include<stdbool.h>
typedef long long ll;//数据到10的14次方 要开long long 
bool isprime(ll n){
    if(n == 1||n%2==0&&n!=2) return false;//先把1和除2以外所有偶数筛掉 
    for(ll i = 3 ; i * i <= n  ; i +=2 )//遍历到根号n,且只遍历奇数 
        if(n % i == 0) return false;
    return true;
}


void solve(){
    ll n,m;
    scanf("%lld%lld",&n,&m);
    if(n==1||m==1)
    {
        if(isprime(n*m)) printf("YES\n");
        else printf("NO\n");
    }else{
        printf("NO\n");
    }
    
}
int main()
{
    solve();
}

E题(神奇的谕示裁定枢机)

        每次把物品尽可能平均的分成 m+1 堆, 把其中 m​ 堆放到天平上,如果平衡,重物就不在天平的那一堆里,否则在最重的那一堆里。所以最劣情况下每次 n 至少被缩小为 ⌈n/(m+1)⌉(向上取整)。

#include<stdio.h>
int main()
{
    int n,m,ans;
    scanf("%d%d",&n,&m),ans=0;
    while(n>1) n=n/(m+1)+(n%(m+1)?1:0),ans++;
    printf("%d\n",ans);
    return 0;
}

F题(金币)

        怎样才能确定一个人是否能赢得冠军?显然,他必须参加所有的游戏(否则我们将增加对手的金币数量)。

        金币数量从大到小排序。这个人获胜的条件是他的金币加上比他少的所有人的金币的数量要大于等于前面那个人的。如果这个人就获胜不了,那么后面的比他金币数量少的就都不能获胜

        所以我们先计算所有人的金币数量,然后比较的时候每循环一下减去自己本身的与后面的人比较。为了排序方便使用了C++的方法。

#include <bits/stdc++.h>
using namespace std;
struct sd{
    int a,b;
};//结构体,分别记录这个人的金币和他的编号
bool cmp(struct sd t1,struct sd t2)
{
    return t1.a>t2.a;
}
int main()
{
    int n;
    cin >> n;//输入
    while(n>0)
    {
        struct sd t[200005];
        n--;
        int m,sums=1,s;
        long long int sum=0;
        cin>> m;
        int a[m+1]={0};
        for(int i=1;i<=m;i++)
        {
            cin >> t[i].a;
            sum=sum+t[i].a;//记录所有金币的数量
            t[i].b=i;
        }
        sort(t+1,t+1+m,cmp);//从大到小排序
        sum=sum-t[1].a;
        a[t[1].b]=1;//最多金币的一定能获胜
        for(int i=2;i<=m;i++)
        {
            if(sum>=t[i-1].a)
            {
                sums++;
                sum=sum-t[i].a;
                a[t[i].b]=1;
                if(i==m)
                {
                    if(t[m].a<t[m-1].a)
                    {
                        a[t[i].b]=0;
                        sums--;
                    }
                    
                }
            }
            else
            {
                break;
            }
        }
        printf("%d\n",sums);
        for(int i=1;i<=m;i++)
        {
            if(a[i]==1)
            {
                printf("%d ",i);
            }
            
        }
        printf("\n");
    }
    return 0;
}

G题(输出WAGD)

        分别记录w和W,a和A,g和G,d和D的输入个数,不断按照WAGD的顺序输出,超出个数的字母跳过继续顺序输出剩下有剩余的字母

#include <stdio.h>

int main(){

    char a[10001],ch;

    char b[4]={'W','A','G','D'};

    int c[4]={0},num=0;

    while((ch=getchar())!='\n'){

        num++;

        if(ch=='w' || ch=='W')

            c[0]++;

        if(ch=='a' || ch=='A')

            c[1]++;

        if(ch=='g' || ch=='G')

            c[2]++;

        if(ch=='d' || ch=='D')

            c[3]++;

    }

    while(c[0]!=0||c[1]!=0||c[2]!=0||c[3]!=0){

    for(int j=0;j<4;j++){

        if(c[j]!=0){

            printf("%c",b[j]);

            c[j]--;

        }

    }

    }

    return 0;

}

H题(纵向排版)

        需要考虑到给定的字符串长度不是N的整数倍的情况,最后一列可能不足N个字符,需要添加,用双层嵌套循环找规律,改变字符的输出顺序。

#include <stdio.h>

#include <string.h>

int main()

{

    int n,num,k=0,x,l,i;

    char ch[1100]={0};

scanf("%d\n",&n);

while((ch[k]=getchar())!='\n'){

        k++;

    }

    x=k;

    if(k%n!=0){

        for(i=0;i<n-k%n;i++){

            ch[x++]=' ';

        }

    }

    l=x/n;

    for(i=0;i<n;i++){

        for(int j=0;j<l;j++){

            printf("%c",ch[j*n+i]);

        }

        printf("\n");

        }

        return 0;

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值