2022NIT 蓝桥杯校赛 简单题解

本文提供了2022NIT蓝桥杯校赛的详细题解,涵盖从简单的条件判断题到涉及算法如二分搜索、深度优先搜索及01背包等问题,适合参赛者及初学者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2022NIT 蓝桥杯校赛 简单题解

A.考试周

  • if或者switch都可以,签到题,不会写的话建议重修C语言…
#include<iostream>
#include<cstdio>
using namespace std;

int main()
{
    int n;
    scanf("%d",&n);
    if(n == 1) printf("Kun were studying Higher mathematics\n");
    else if(n == 2) printf("Kun were studying Linear algebra\n");
    else if(n == 3) printf("Kun were studying Principle of computer composition\n");
    else if(n == 4) printf("Kun were studying Database system concept\n");
    else if(n == 5) printf("Kun were studying Data structures and algorithms\n");
    else
    {
        printf("Kun were playing basketball\n");
    }

    return 0;
}

B.01串

  • 斐波那契数列,其实只要例举n的1 2 3 4…,就可以发现一些规律了,这里来讲一讲常规的思考方式:首先用f(k)表示表示n=k时X字符串的数量,那么第k位有两种情况:0和1,假如第k位为1,那么前一位不管是多少都是合法的,所以就有f(k-1)个X字符串,假如为0,那么前一位就必须是1才能合法,而前一位是1时就有f(k-2)个X字符串。把两种情况合在一起就是f(k)=f(k-1)+f(k-2),即斐波那契数列
  • 代码上也有细节,首先当n过大,肯定是超出了int的范围,题目也要求结果模200003,这个也是需要注意的
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long int LL;//使用long long int类型
int main(){
    int n;
    scanf("%d",&n);
    LL a = 1 , b = 2;
    if(n == 1) printf("%d\n",1);
    else if(n == 2) printf("%d\n",2);
    else
    {
        LL y = 0;
        for(int i = 3 ; i <= n ; i ++ )
        {
            y = (a + b)%200003;
            a = b;
            b = y;
        }
        printf("%lld\n",y);
    }
    return 0;
}

C.得分

  • 比较简单的字符串模拟
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        char a[100];
        scanf("%s",a);
        int l = strlen(a);
        int ans = 0;
        for(int i = 0; i < l ; i ++ )
        {
         int no = 0;
            while(a[i] == 'O')
            {
                no++;
                ans += no;
                i++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

D.涂色

  • 由题意可知最后一笔画一定是完整的一行或者一列,我们只需要判断方格图是否存在完整的行或者列就行了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

char g[8][8];
int main()
{
    for(int i = 0 ; i < 8 ; i ++ )
     scanf("%s",g[i]);
    
    for(int i = 0 ; i < 8 ; i ++ )
    {
        int j;
        for(j = 0 ; j < 8 ; j ++ )
         if(g[i][j] != 'R')
            break;
        if(j >= 8)
        {
            printf("R\n");
            break;
        }

        int k;
        for(k = 0 ; k < 8 ; k ++ )
         if(g[k][i] != 'B')
            break;
        if(k >= 8)
        {
            printf("B\n");
            break;
        }
    }
    return 0;
}

E.捉迷藏

就是求两个点之间的连线上有没有其它点
根据直线在平面直角坐标系上斜率的定义,点(x,y)在点(x1,y1)和点(x2,y2)所确定的线段上,当且仅当(x-x1):(y-y1)=(x-x2):(y-y2)=(x1-x2):(y1-y2)(范围x1<=x<=x2,y1<=y<=y2)
由此,我们可以得知,两个点之间存在其它的点的话,必然有(x-x1):(y-y1)=(x-x2):(y-y2),因为x,y,x1,y1,x2,y2都是整数,那么(x-x1),(y-y1),(x-x2),(y-y2),(x1-x2),(y1-y2)必然都是整数,且他们的比值相等。易证,如果存在这样的一组数,那么gcd(abs(x1-x2),abs(y1-y2))!=1,所以,我们只需求出gcd的值。
gcd即是最大公因数,辗转相除法求得

#include<iostream>
#include<cstdio>
using namespace std;

int n,ax,ay,bx,by;
int gcd(int x,int y)
{
	if(y==0) return x;
	  else return (gcd(y,x%y));
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d%d",&ax,&ay,&bx,&by);
		if(gcd(abs(ax-bx),abs(ay-by))==1) printf("DANGER\n");
		  else printf("SAFE\n");
	}
	return 0;
}

F.篮球

  • 二分算法,建议先去写计协公告题单里的二分那几道,可能会好理解一点,其实题目已经提示了“求最大值的最小值”,这里就可以开始考虑是否要二分这个最小值了
  • 同时由于数据范围的原因,也要注意long long int之类的,就不多提了
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long int LL;
const int N = 1e5 + 10;
LL a[N];
int n,m;

bool check(LL mid)
{
    int cnt = 0;
    LL res = 0;
    for(int i = 1 ; i <= n ; i ++ )
    {
        if(a[i] > mid)
            return 0;
        if(res + a[i] > mid)//如果这一段超过了我们当前规定的最大值mid,那就必须分段了,最大值就是不是mid
        {
            res = a[i];
            cnt++;//cnt记录的是段数
            if(cnt > m - 1)
             return 0;
        }
        else res += a[i];
    }
    return 1;
}


int main()
{
    scanf("%d %d",&n,&m);
    LL l = 0 ,r = 0;
    for(int i = 1 ; i <= n ; i ++ )
    {
        scanf("%lld",&a[i]);
        r += a[i];
    }

    while(l < r)
    {
        LL mid = (l + r) / 2;
        if(check(mid))
         r = mid;
        else
         l = mid + 1;
    }

    printf("%lld\n",l);

}

G.素数环

  • 深度优先搜索,建议先去写计协公告题单里的深度优先搜索那几道,可能会好理解一点
  • 一道非常经典的DFS题,在原题的基础上对于输入和测试数据都简化了很多
  • 答案可以直接看这个,附带讲解:UVA524:素数环

H.KTV

  • 01背包问题,每首歌曲相当于物品,歌曲的长度相等于物品重量,每个歌曲的价值为1
  • 有几个细节需要注意,第一个就是必须要满足歌曲数量最大,再去考虑时间。还有就是要在“时间结束前”唱额外的那首歌,也就是说假如有100秒时间,有两首歌一首是40秒一首是60秒,其实是不可以同时唱的,因为题目规定必须要唱额外的那首歌,所以至少得预留一秒给这首歌,一首40秒和一首59秒就可以。以及对于dp数组的初始化用的是-1而不是0,主要原因是对于第一首的选取问题,赋值0的话会出现决策失误的情况。题目也规定了不能出现空窗期,所以必须是连续唱歌
#include<iostream>
#include<cstring>
using namespace std;
int T,t,n,a[510],dp[510][500*180+10];
int main(){
        scanf("%d%d",&n,&t);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        dp[0][0]=0;
        for(int i=1;i<t;i++)dp[0][i]=-1;

        int ans=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<t;j++){
                dp[i][j]=dp[i-1][j];
                if(j>=a[i]&&dp[i-1][j-a[i]]>=0)
                    dp[i][j]=max(dp[i][j],dp[i-1][j-a[i]]+1);
                ans=max(ans,dp[i][j]);
            }

    }
        for(int j=t-1;j>=0;j--)
            if(dp[n][j]==ans){
                printf("%d %d\n",ans+1,j+219);
                break;
            }
    return 0;
}

J.油饼

  • 贪心和选择排序的思想,我们可以把每一次的最大一位数都给转到最上面。具体的代码细节有点麻烦

I.回家

  • 最短路径+二分:最短路径使用堆优化版Dijistra算法,SPFA会被卡,别问我怎么知道的
  • 没有学过数据结构-图论不建议深究本题,答案在这里:通往奥格瑞玛的道路
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值