• HGNU
  • 2023年黄冈师范学院第三届『小白杯』新生赛题解

  • @ 2023-11-28 9:29:37

『小白杯』黄冈师范学院程序设计
第三届新生赛题解

A:LivingsequenceA:Living-sequence:

一般的暴力写法是根据n循环并判断每个数字是否含有9,以此得到第n项,但是n的数据范围是1e9级别,暴力的写法被卡掉了。

由题意可知,含9的数字被删除,在具体的数字上表示为逢9进1,所以对于给定的n,转化成9进制表示即可。 时间复杂度O(log n)

题解代码:

#include<stdio.h>
int res[100];
int main(){
    int n;
    scanf("%d",&n);
    int size=0;
    while(n){
        res[++size]=n%9;
        n/=9;
    }
    for(int i=size;i;i--)printf("%d",res[i]);
}

BB:RikkaRikka的外卖:

本题的难点就在于对双循环的优化,可以通过预处理的方式来解决,求连续一段区间(l,r)的总和,可以看成求前r项和减去前l-1项和,那么我们就可以提前将前n项和求出来,然后求连续k天的总和就不需要用循环来再求一遍。

当然,也有另一种解法,也是过了的人都用的解法,就是维护一个长度为k的区间,让这个区间不断的向后面移动,每次都加上加入到区间中的数和减去移除区间的数,然后比较更新最大值,从头到尾跑一遍就能得到最大值。

还有就是本题的数据比较大,需要开long long.

题解代码:

解法一:

#include <iostream>
using namespace std;

const int N=1e5+10;

long long a[N],s[N];    //s数组用来记录前n项和

int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        s[i]=s[i-1]+a[i];   //s[i]表示前i项和
    }
    long long sum=0;
    for(int i=k;i<=n;i++)
    {
        sum=max(sum,s[i]-s[i-k]);   //s[i]-s[i-k]表式第i-k+1项到第i项之和
    }
    cout<<sum<<endl;
}

解法二:

#include <iostream>
using namespace std;

const int N=1e5+10;

long long a[N];

int main()
{
    int n,k;
    cin>>n>>k;
    long long sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(i<=k)sum+=a[i];  //先计算出前k项
    }
    long long ans=sum;
    for(int i=k+1;i<=n;i++) //从第k+1项开始,加上第i项,减去前面第i-k项,然后比较和之前最大的值,然后更新最大值
    {
        sum+=a[i];
        sum-=a[i-k];
        ans=max(sum,ans);
    }
    cout<<ans<<endl;
}

CC:谁才是第一名:

本题为此次比赛的签到题,先比较过题数,过题数不相同取直接最大值,过题数相同则比较过题时间,取过题时间更小的即可。

题解代码:

#include<bits/stdc++.h>
using namespace std;
int main() {
    int a,b,c;
    int x,y,z;
    scanf("%d %d %d",&a,&b,&c);
    scanf("%d %d %d",&x,&y,&z);
    if(a>x)
    {
        printf("QQLover");
        return 0;
    }
    else if(a<x)
    {
        printf("VXLover");
    }
    else if(a==x)
    {
        if(b+(c-1)*20>y+(z-1)*20)
        {
            printf("VXLover");
            return 0;
        }
        else
        {
            printf("QQLover");
            return 0;
        }
    }
    return 0;
}

DD:最长回文子串:

本题介绍其中一种解法:枚举给定字符串的左右端点,如相同则往中间移动(左端点的左指针向右移动,右端点的指针向左移动),直到不相同为止,每次记录一次回文子串的最大长度即可。复杂度O(n^3)。

题解代码:

#include <stdio.h>
#include<string.h>
const int N=1e3+10;

int max(int a , int b)
{
    if(a>b) return a;
    else return b;
}
  int main()
  {
        char s[N];
       scanf("%s",s);
           int len = strlen(s);
            int mxl = 0;
            for(int i=0 ; i<len-1 ;i++)
            {
                for(int j=i+1 ;j<len ;j++)
                {
                    int l=i , r=j;//左指针指向i,右指针指向j
                    while(l<r)
                    {
                        if(s[l]!=s[r])break;//不同则退出循环
                        else{
                        r--;l++;
                        }
                    }
                    if(l>=r)
                    {   
                        int len = j-i+1;//j-i+1为此时枚举的回文子串长度
                        mxl = max(mxl , len);
                    }   
                }

            }
          printf("%d\n",mxl);
  }

EE:FlyFly想当滋崩狗:

检查和原点的曼哈顿距离是否为奇数,如果存在偶数就会被追上。

题解代码

#include<bitsdc++.h>
using namespace std;

int main(){
    int n, x, y;
    // scanf("%d %d %d", &n, &x, &y);
    cin >> n >> x >> y;

    int tx, ty;
    int judge = 1;
    for (int i = 1; i <= n; i ++){
        // scanf("%d, %d", &tx, &ty)
        cin >> tx >> ty;

        int dis = abs(x - tx) + (y - ty);
        // abs() 为求绝对值
        if(dis % 2 == 0)
            judge = 0;
    }
    cout << (judge ? "YES" : "NO") << endl;
}

FF:谁才是第一名ProMaxPro-Max

本题为签到题的加强版,先比较过题数,过题数不相同取过题数高的并更新此时的第一名,过题数相同则比较过题时间,取过题时间更小作为第一名并更新即可。

题解代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a,b,c;
    int max=-1,max2=-1;
    int n;
    int ans;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a>>b>>c;
        if(max2<a)
        {
            ans=i;
            max2=a;
            max=b+(c-1)*20;
        }
        else if(max2==a)
        {
            if(max>b+(c-1)*20)
            {
                ans=i;
                max=b+(c-1)*20;
            }
        }
    }
    printf("%d",ans+1);
}

G:yyG:yy的签到题:

思路就是读入的是一个字符串,不能用int来读,可以用string 或者char数组来读入。

题解代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string s;
        cin>>s;
        char a;
        cin>>a;
        int flag=1;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]==a)
            {
                cout<<i+1<<endl;
                flag=0;
                break;
            }
        }
        if(flag) cout<<"-1"<<endl;
    }
    return 0;
}