选拔赛补题题解

补题的过程很欢乐
debug的快乐

题目1

蒲煜凡学长最近迷上了一个漂亮的小学妹,他想送一朵特别的花给这个小学妹。
他现在有一把N朵漂亮的花,每多花都有a[i]个花瓣,如果有1朵花的花瓣数与其他任意一朵花的花瓣数之差等于2,那么他可以选择把这朵花扔掉,也可以选择丢弃。
请问经过若干次操作之后蒲煜凡学学长能找到唯一的一支特别的花送给小学妹吗?

输入

第一行一个整数t(1<=t<=500)表示测试样例数
每个测试样例第一行一个整数n(1<=n<=1e4)表示花的数量,第二行n个整数ai表示花瓣数。

输出

输出t行"YES"or"NO"

输入样例

1
4
2 4 6 8

输出样例

YES

输入样例

1
5
9 3 5 6 7

输出样例

NO

这个题在比赛时,说实话没看懂,就一直在抠字眼,看不懂题的快乐

赛后经大佬指导,懂了思路,但是再写的过程中仍会出很多错误

这道题需要注意的点
1、花的个数,当只有一朵花时,这朵花就是那支“特别的花”,输出YES
2、当每朵花的花瓣都相同时,选不出“特别的花”,输出NO(这个注意点可以和查重结合一下加判断条件即可)
3、这道题注意查重,因为当我们花瓣数相同的时候,如果可以丢弃一个,那么那些相同花瓣数的花也可以丢弃
4、可以将花瓣数从小到大排序,假设最小或者最大的那朵花为“特别的花”,保证前一朵花可以被后一朵花消掉或后一朵被前一朵消掉,当出现不能消掉的情况是,这个组合的花是不可能挑出“特别的花”的(重点理解)。

清空数组,数组初始化。(小知识点 嘿嘿~)

memset(p,0,sizeof(p));
memset(a,0,sizeof(a));

注意点1

if(n == 1){printf("YES\n");return 0;}

注意点2和注意点3结合

int r = 0;
for(int i = 0;i < n;i ++){ 
	int q = 0;
	scanf("%d",&q);
    if(p[q] == 0){
    	p[q] = 1;
        a[r] = q;
        r ++; 
    }
}
if(r == 1) {printf("NO\n");return 0;}

注意点4

sort(a,a + r);
int flag = 1;
for(int i = 0;i < r - 1;i ++){
	if(a[i + 1] - a[i] != 2) flag = 0;
}

代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 1e6+ 10;

int t,n;
int a[N],p[N];

int main(){
	scanf("%d",&t);
	while(t --){
        memset(p,0,sizeof(p));
        memset(a,0,sizeof(a));
        scanf("%d",&n);
        if(n == 1){printf("YES\n");return 0;}
        int r = 0;
        for(int i = 0;i < n;i ++){ 
            int q = 0;
            scanf("%d",&q);
            if(p[q] == 0){
                p[q] = 1;
                a[r] = q;
                r ++;
            }
        }
        if(r == 1) {printf("NO\n");return 0;}
        sort(a,a + r);
        int flag = 1;
        for(int i = 0;i < r - 1;i ++){
            if(a[i + 1] - a[i] != 2) flag = 0;
        }
        if(flag) printf("YES\n");
        else printf("NO\n");
	}
	return 0;
}

题目2

大多数情况下甘靖学长说普通话时都很标准,但有时却令人抓狂,这件事困扰他很久了,突然有一天,他想通过读数字来纠正他的发音,
但是他不想按正常的顺序读数字,于是他按照某种规律写了一些数字在黑板上,比如如果他想数到9,那么他会把数字写成如下格式:
1 2 6 7
3 5 8
4 9
如果他想数到15,那么他会把数字写成如下格式:
1 2 6 7 15
3 5 8 14
4 9 13
10 12
11
他突然发现他写数字的规律是个蛇形,具体描述是这样的:
对于每一条左下-右上的斜线,从左上到右下依次编号1,2,…,2n-1;按编号从小到大的顺序,将数字从小到大填入各条斜线,其中编号为奇数的从左下向右上填写,编号为偶数的从右上到左下填写

输入

输入一个不大于10000的正整数n,表示要填充到的数字的大小

输出

按规律输出这些数字,相邻两个元素之间用单个空格间隔

输入样例

50

输出样例

1 2 6 7 15 16 28 29 45 46
3 5 8 14 17 27 30 44 47
4 9 13 18 26 31 43 48
10 12 19 25 32 42 49
11 20 24 33 41 50
21 23 34 40
22 35 39
36 38
37

比赛时刚看到这个题的时候感觉会很简单,就是找规律(但是我找不到,我个废物
后来才发现这个题很有意思(debug一年),大佬讲完,刚开始还没有太深印象,后来自己补题时发现大佬的思路巧妙

这个题我们要大致判断二维数组的大小,暴力解决从1+到10000,大概需要210行210列(为什么行列相同看一下题就可以理解)来存

注意点

1、计算需要的行数列数。
2、思考问题的角度,斜着给数组赋值,同时斜着的每一行各元素的行数列数加起来是定值,在等于n的时候停止给数组赋值,横着输出每一个数.
3、输出时候while巧妙运用。

注意点1

for(int i = 1;sum < n;x_r ++,sum += i,i++);

注意点2

斜着给数组赋值(是我没想到的)

for(int i = 1;i <= x_r;i++)
        for(int j = 1;j <= i;j ++){
            if(i % 2 == 1){
                a[i + 1 - j][j] = ++p;
            }else{
                a[j][i + 1 - j] = ++ p;
            }
            if(p == n) break;
        }

注意点3

横着输出,用while,可以很巧妙的,避免输出0的状况(在这摔过两次)

for(int i = 1;i <= x_r;i ++){
        if(i>1)printf("\n");
        int k = 1;
        while(a[i][k]) printf("%d ",a[i][k ++]);
    }

代码

#include <iostream>
#include <cstdio>

using namespace std;

int n;
int a[210][210];

int main(){
    scanf("%d",&n);
    int x_r = 0,sum = 0;
    int p = 0;
    for(int i = 1;sum < n;x_r ++,sum += i,i++);
    for(int i = 1;i <= x_r;i++)
        for(int j = 1;j <= i;j ++){
            if(i % 2 == 1){
                a[i + 1 - j][j] = ++p;
            }else{
                a[j][i + 1 - j] = ++ p;
            }
            if(p == n) break;
        }
    for(int i = 1;i <= x_r;i ++){
        if(i>1)printf("\n");
        int k = 1;
        while(a[i][k]) printf("%d ",a[i][k ++]);
    }
    return 0;
}

不得不说,大佬们的思路很巧妙,yyds!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半碗无糖蓝莓冻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值