第五次周赛总结

题目总链接:

https://nuoyanli.com/contest/34/problems

A:Fenoix超厌恶xxx

题目链接:

https://nuoyanli.com/contest/33/problem/B

题面:

在这里插入图片描述

题意:

先输入一个整数n,代表文件的长度。接着输入长度为n的字符串,这个字符串只由小写字母组成,我们需要的是不包含“xxx”的字符串,如果文件名最初就不包含字符串“xxx“,则输出0,其他情况就输出我们需要删除最少多少个字符才满足文件名不包含”xxx“的字符串。

思路:

这道题目的思路就是每当出现3个连续的”xxx“的就需要删除一个x;
例如:
xxxx 我们首先判断前面3个字符,都为xxx,则我们删除最前面那个。后面再判断2,3,4是三个连续的xxx,我们就需要删除一个。
所以这道题目我们就只需要一个一个判断出现了多少次”xxx“连续的情况,每次出现一次就代表我们要删除一个,然后就可以得出需要删除的最小字符串数目。

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int main()
{
    long long n,ans=0,i;
    scanf("%lld",&n);
    char a[1000];
    scanf("%s",a);
    for(i=0;i<n;i++)
    {
        if(a[i]=='x'&&a[i+1]=='x'&&a[i+2]=='x')//判断是否出现3个连续的x
        {
            ans++;//每当出现一次就意味着要删除一个,所以删除的字符串长度加1
        }
    }
    printf("%lld",ans);//直接输出最后需要删除的字符串长度
}

B:来呀,贪心呀~

题目链接:

https://nuoyanli.com/contest/33/problem/G

题面:

在这里插入图片描述

题意:

先输入一个整数,代表有m组数据,接下来输入一个n代表有n个活动,随后输入两个整数分别代表第i个活动的起始和结束时间。我们需要输出最多能够安排的活动数量。

思路:

这就是个简单的贪心,你就只考虑安排的活动数目最多,我们首先将每个活动按照结束的时候进行排序,当结束时候相等时,我们就按照开始越晚的排在前面,这时候这个活动的占的时间是最少的,然后我们进行判断,最早结束的那个活动是肯定要选的,然后按照顺序判断后面的活动的开始时间是否大于上一个活动的结束时间,一旦大于就选择这个活动,因为我们活动是按照结束时间进行排序,所以选择的一定是满足条件并将用时最短,然后就一次一次的判断。就可以得出最后的答案。

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct p//先定义一个结构体来存储那个活动的开始时间和结束时间
{
    int s;
    int e;
}a[100000];
bool cmp(p a,p b)//对活动按照结束时间进行排序
{
    if(a.e==b.e)
    {
        return a.s>b.s;
    }
    else
        return a.e<b.e;
}
int main()
{
    int m;
    scanf("%d",&m);
    while(m--)
    {
        int n,i;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&a[i].s,&a[i].e);
        }
        sort(a,a+n,cmp);
        int ans=1,j,k=0;
        for(i=1;i<n;i++)
        {
                if(a[i].s>a[k].e)//判断是否存在一个活动大于已经选择的活动的结束时间
                {
                    ans++;
                    k=i;//选择这个活动,我们下面就需要有没有一个活动存在活动开始时间需要这个活动的结束时间
                }
        }
        printf("%d",ans);
        if(m!=0) printf("\n");
    }
}

C:Fenoix的趣事

题目链接:

https://nuoyanli.com/contest/33/problem/D

题面:

在这里插入图片描述

题意:

先输入一个只由‘0’和‘1’组成的字符串,其中0代表一个球队的成员,1也代表一个球队的成员,我们需要判断是是否存在一个球队的成员有至少7个连续的站在一起,这种情况就是危险的,输出YES,其他情况就输出NO.

思路:

这道题目的基本思路就是来查找这个字符串中有没有重复的字符连续出现出现7次就可以了,如果有重复的字符出现7次则证明是危险的,如果没有,就是安全的。

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int main()
{
    int len,i,ans=1,flog=0;//这里ans代表的是通一个队伍的连续成员,无论如何都是有一个连续的,所以这里ans初始定义为1,就代表总是1个人连续
   char a[10000];
   scanf("%s",a);
   len=strlen(a);
   for(i=0;i<len-1;i++)
   {
       if(a[i]==a[i+1])
       {
           ans++;//一旦出现连续的重复字符,就连续的球员数目加1
       }
       else
       {
           ans=1;//一旦出现一个不重复的就把连续人数清0.
       }
       if(ans>=7)//这里先进行判断,是否出现过连续出现重复的字符7次,一旦出现就证明就是危险的,直接输出YES,然后跳出循环
       {
           printf("YES");
           break;
       }
   }

   if(ans<7)
   {
       printf("NO");//这里来判断最后ans是否小于7,如果小于7,就证明是安全的,输出NO.
   }
   return 0;
}

D:lwm学姐的木屋

题目链接:

题面:

在这里插入图片描述
在这里插入图片描述

题意:

先输入一个整数K,就是需要测试的次数,对于每一个要测试的例子,我们先输入一个整数n代表拥有的木板数目,之后输入n个数字,代表这n个木板数目的长度,我们需要判断的是这些木板能够组成的最大正方形的边长为多少。然后输出这些木板构成正方形的最大可能边长的长度。

思路:

这道题目我的基本思路就是先把木板的长度进行从小到大排序,然后组成的正方形的边长只可能是从1到最大值之间出现,然后我们就可以从1到最大值进行遍历,我们依次进行判断,如果就是超给这个长度的木板数目大于这个边长数,就讲长度进行赋值,然后一直遍历到最大值,就可以得出可以得到的最大的正方形边长。

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int main()
{
    long long k;
    scanf("%lld",&k);
    while(k--)
    {
        long long n,ans=0,maxe=1,i,j;
        scanf("%lld",&n);
        long long a[n+10];
        for(i=0;i<n;i++)
        {
            scanf("%lld",&a[i]);
        }
        sort(a,a+n);//对其进行排序来得到最大值
        for(i=1;i<=a[n-1];i++)//从1到木板的最大值进行遍历
        {
             ans=0;
             for(j=0;j<n;j++)
             {
                 if(a[j]>=i)//判断所有木板中大于i的个数
                 {
                     ans++;
                 }
             }
             if(ans>=i)//如果存在大于i的数大于i个,就可以组成这个边长的正方形
             {
                 maxe=i;//将其进行赋值
             }
        }
        printf("%lld",maxe);//输出最大满足的正方形边长
        if(k!=0) printf("\n");
    }
}

E:Fenoix的针对

题目链接:

https://nuoyanli.com/contest/33/problem/K

题面:

在这里插入图片描述

题意:

题意非常简单,就是多组输入,每一个数字输入一个对应的蛇形矩阵,每一个数字以%2d的形式输出,并且每个数字之间都有一个空格,最后每次输出答案还要加一行空格。

思路:

这道题目还是找规律,都是找到规律用代码实现还是比较复杂的。这里先详细讲一种,后面单独开个博客详细讲讲其他方法。

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
int main()
{
    int n;
    int a[100][100];
    while(scanf("%d",&n)!=EOF)
    {
        int i,j,b,c;
        a[0][0]=1;//首先将第一位初始为1
        for(i=1; i<n; i++)
        {
            a[i][i]=a[i-1][i-1]+2*i;//根据规律可以知道对角线上的数字是满足这个等式关系的
        }
        for(j=1; j<n; j++)
        {
            b=j;
            c=j;
            if(j%2==1)//判断是否为奇数位
            {
                while(b--)//这里b--循环可以让第一次运行始终可以用到对角线的元素,从而有了参照物,而且成功把每个对角线元素以上的元素都赋值了。,即当j=3时,我们就把5,6,7,12,11,10全部完成赋值。就相当把每一次for的执行和while的执行,就相当完成了一个墙角赋值的计算。
                {
                    a[b][c]=a[b+1][c]-1;//当列为奇数时,他等于下一个偶数序减1
                    a[c][b]=a[c][b+1]+1;//当行为奇数时,他等于下一个偶数行加1
                }
            }
            else
            {
                while(b--)
                {
                    a[b][c]=a[b+1][c]+1;//当列为偶数时,他等于下一个奇数列加1
                    a[c][b]=a[c][b+1]-1;//当行为偶数时,他等于下一个奇数列减1
                }
            }
        }
        for(i=0; i<n; i++)
        {
            for(j=0; j<n; j++)
            {
                printf("%2d ",a[i][j]);
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

F:说是栈你会做么?

题目链接:

https://nuoyanli.com/contest/33/problem/H

题面:

在这里插入图片描述

题意:

输入一个字符串,长度不超过50,然后这个字符串是由1一个空串不断加ab而成的就是一个好串,如果不是,则不是好串,如果是好串输出Good,不是好串输出Bad。

思路:

这道题目就是要不断找到一队匹配的ab,当也一队匹配的ab就把他们两个一起删除,因为是可以插入在任意一个位置的,所以这个ab不一定是连续的,我们就不断的判断,我们每插入一个ab就在两边或者中间插入,所以匹配的ab不是连续的,就是一个在开头,一个在结尾,我们就需要判断下一位而结尾位有没有匹配的b,下一位有匹配的就跳过下一位,最后一位有匹配的就删除最后一位。然后判断最后是否为空串。

参考代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
using namespace std;
char s[100005];
int main()
{
    scanf("%s",s);
    int k=strlen(s),i;
    for (i=0; i<k; i++)
    {
        if (s[i]=='b')//如果重新一个单独的b,就证明这个字符串不可能是一个空串加ab得到的,所以他一定不是一个好串。
            break;
        if (s[i]=='a')//先判断这个字符串是否为a
        {
            if (s[i+1]=='b')//如果下一个为b则两个直接跳过,所以i=i+1
            {
                i=i+1;
            }
            else if(s[k-1]=='b')//如果最后一个为b,最后也可以使得开头的a与结尾的a相消
            {
                k--;//然后这个字符串的长度减1.
            }
            else
                break;//一旦这两种情况都不存在,就证明这个a没有对应的b,所以他肯定不是一个空串得到的
        }
    }
    if (i==k)//如果最后运行到了最后,就证明没有一个多余的字符了
        printf("Good");
    else//如果没有运行到最后,就证明重新个单独的a或者单独的b,或者无法匹配为ab的字符
        printf("Bad");
    return 0;
}

G:cgy学长爱吃糖果

题目链接:

https://nuoyanli.com/contest/33/problem/F

题面:

在这里插入图片描述

题意:

先输入一个整数,代表T组输入·。然后每组输入一个整数n,代表有n中口味,然后输入每种口味的个数,cgy学长每次只吃两个糖果,并且要求两种糖果为不同的口味,现在我们就需要判断cgy学长是否可以把所有糖果吃完,如果可以输出NICE!!!,如果不可以****!!!。

思路:

这道题目首先我们一定可以知道的只有当糖果的总数为偶数的时候才可能全部吃完,这是一个必要的条件。然后我们就接着思考,我们需要把所有糖果吃点,我们就一定是先把两个最多的糖果先个吃掉一个,接着再把最多的两种糖果各吃掉一个,最后我们就可以得出,只需要当总数减去最大值之后的那个数字大于等于其中数目最多的一种糖果的数目,就一定是可以吃完的,所有这道题目只要考察的就是思路题,代码其实并不复杂。

参考代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
using namespace std;
int main()
{
    long long t;
    scanf("%lld",&t);
    while(t--)
    {
        long long n,sum=0,i,ans;
        scanf("%lld",&n);
        int  a[n+10];
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            sum=sum+a[i];//把所有糖果的总数求出来
        }
        sort(a,a+n);//得出这些种类的糖果中数目最多的糖果
        ans=sum-a[n-1];
        if(sum%2==0&&a[n-1]<=ans)//当糖果总数为偶数并且总数减去数量最多的数目大于数量最多的就一定可以吃完
        {
            printf("NICE!!!\n");
        }
        else//其他情况就吃不完
        {
            printf("****!!!\n");
        }
    }
    return 0;
}

I:我也太难了

题目链接:

https://nuoyanli.com/contest/33/problem/J

题面:

在这里插入图片描述

题意:

这就是一道简单的递归题。

思路:

关于递归我们就注意一些问题,我们使用递归一旦数据过大就可以会出现大大小小的问题,所以建议是数据类型使用long long ,而且最后使用记忆化,还有递归函数一定是有结束条件的,递归的公式根据题目要求自行分析就行了。递归函数的定义基本模板就在下面的参考代码中,自己参考学习。
递归函数的基本模板就是

long long di(long long n)//递归函数的定义
{
    if(re_sum[n])
    {
        return re_sum[n];//这是属于记忆化的过程,这个可以基本每个递归函数都写上
    }
    if(n==1||n==2)
    {
        return x;//递归结束的条件,这个是可以改变的,但是每个递归函数都应该有递归结束的条件
    }
    return re_sum[n]=di(n-1)+di(n-2);//递归得到的最后的式子,式子是根据题目意思来更改的
}

参考代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
using namespace std;
long long re_sum[10000];
long long di(long long n)//递归函数的定义
{
    if(re_sum[n])
    {
        return re_sum[n];//这是属于记忆化的过程
    }
    if(n==1||n==2)
    {
        return 1;//递归结束的条件
    }
    return re_sum[n]=di(n-1)+di(n-2);//递归得到的最后的式子
}
int main()
{
    long long  t;
    scanf("%lld",&t);
    while(t--)
    {
        long long n,sum;
        scanf("%lld",&n);
        sum=di(n);//引用递归函数
        printf("%lld",sum);
        if(t!=0) printf("\n");
    }
}

J:来自Fenoix的刁难

题目链接:

https://nuoyanli.com/contest/33/problem/L

题面:

在这里插入图片描述

题意:

先输入一个整数n,代表数组中的元素个数,然后输入n个数组中的元素。我们首先需要得出输删除重复的数字后剩余的数字的个数,然后换一行输出只想保留数组的每个元素,是从数组最右边第一次出现的元素。

思路:

这道题目一看要去重的就可以猜测需要使用桶排,然后输出从数组右边出现第一次出现的元素,我们就可以先从右到左进行判断,将不重复的数字存储到另一个数组当中去,然后最后在逆序把另一个数组输出了,就实现了题目的要求。

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int main()
{
    long long n,ans=0,i,flog=1,maxe=-1,k=0;
    scanf("%lld",&n);
    long long a[n+10];
    long long vis[10000];
    long long b[n+10];
    memset(vis,0,sizeof(vis));
    for(i=0;i<n;i++)
    {
        scanf("%lld",&a[i]);
        if(a[i]>maxe)
        {
            maxe=a[i];//找出这n个数字中的最大数
        }
    }
    for(i=0;i<n;i++)
    {
        vis[a[i]]++;//对其进行桶排,就是将下角标作为数组的数值
    }
    for(i=0;i<=maxe;i++)
    {
        if(vis[i]>0)//判断是否大于0,大于0则数组中存在数字i
        {
            ans++;//不重复的数字就加1.
        }
    }
    printf("%lld\n",ans);//直接输出不重复的数字个数
    memset(vis,0,sizeof(vis));//再次将这个数组进行清0
    for(i=n-1;i>=0;i--)//再将其进行逆序桶排
    {
        vis[a[i]]++;
        if(vis[a[i]]==1)
        {
            b[k]=a[i];//将出现的数字存储到了一个数组中间去
            k=k+1;//每运行一次加k加1
        }
    }
    for(i=k-1;i>=0;i--)
    {
        if(i==k-1) printf("%lld",b[i]);//最后再逆序输出存储的数值,因为题目要求是右边出现的第一次出现的元素,如果你直接逆序判断的话,就后刚好和题目要求相反,所以最后这里是需要在逆序输出的
        else printf(" %lld",b[i]);
    }
}

K:Fenoix的签到题

题目链接:

https://nuoyanli.com/contest/33/problem/E

题面:

在这里插入图片描述

题意:

先输入一个整数n,表示整数的个数,接着输入这n个正整数,然后我们判断最长的连续的递增序列。输出最长的递增序列的的长度

思路:

这道题目就可以判断每当后面那个数字大于前面那个数字就加1,一旦断开我们就可以先存储起来这个第一个序列的长度,然后再当存在连续的递增序列的长度,就与之前的进行判断,长的那个序列长度进行保存,最后就可以得出这其中最大的递增序列的长度了。

参考代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
int main()
{
   int n,i,ans=1,maxe=0;//这里ans定义为1是ans所代表的是递增序列的长度,就递增序列的长度这样初始长度都是为1的,所有定义为1.
   scanf("%d",&n);
   int a[n+10];
   for(i=0;i<n;i++)
   {
       scanf("%d",&a[i]);
   }
   for(i=1;i<n;i++)
   {
       if(a[i]>a[i-1])//判断后一个数是否大于前一个数字,大于就加1.
       {
           ans++;
       }
       else
       {
           if(ans>maxe)//判断ans的长度是否大于maxe,如果大于就将ans的数值赋值给maxe,这就是一个找最大递增序列的长度的过程
           {
               maxe=ans;
           }
           ans=1;//一旦出现不相等的长度就要重新进行清0.
       }
   }
   if(ans>maxe)//最后再进行一次判断,因为可能还出现最后一个和前一个是相等的,就不会执行for循环中else里面的语句,所有我们最后还要判断一次
   {
       maxe=ans;
   }
   printf("%d",maxe);//最后输出maxe就是最长的递增序列
}
发布了55 篇原创文章 · 获赞 12 · 访问量 8985

猜你喜欢

转载自blog.csdn.net/qq_45740533/article/details/103219922