洛谷题型摘选(二)


一、杨辉三角

给出 n(n≤20),输出杨辉三角的前 n 行。
如果你不知道什么是杨辉三角,可以观察样例找找规律。

1.样例

> 输入:
6
> 输出:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

2.做题思路

又是似曾相识的感觉,和之前的《直角三角形》长得好像,但是这次输出的三角形,每个数的值是和上一行的2个数有关系的,所以很显然就是要考二维数组,然后再使用2个for循环把他按照格式输出。

3.代码如下:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	static int a[20][20];
	int n;
	scanf_s("%d", &n);
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < i + 1; j++)
		{
			if (i == 0 || j == 0 || i == j) a[i][j] = 1;	/* 使每行两侧的数等于1 */
			else a[i][j] = a[i - 1][j - 1] + a[i - 1][j];	/* 非两侧的数的值为上一列前后2两数之和 */
			printf("%d ", a[i][j]);		/* 输出该数 */
		}
		printf("\n");	/* 每行结束需要换行 */
	}
	return 0;
}

二、珠心算测验

某学校的珠心算老师采用一种快速考察珠心算加法能力的测验方法。他随机生成一个正整数集合,集合中的数各不相同,然后要求学生回答:其中有多少个数,恰好等于集合中另外两个(不同的)数之和?
最近老师出了一些测验题,请你帮忙求出答案。

输入格式:
第一行包含一个整数nn,表示测试题中给出的正整数个数。
第二行有nn个正整数,每两个正整数之间用一个空格隔开,表示测试题中给出的正整数。

输出格式
一个整数,表示测验题答案。

(本题目为2014NOIP普及T1)

1.样例

> 输入:
4
1 2 3 4
> 输出:
2

样例说明
由1+2=3,1+3=41+2=3,1+3=4,故满足测试要求的答案为2。
注意,加数和被加数必须是集合中的两个不同的数。

2.做题思路

这道题是不是和上次那个《两数之和》特别特别像呢? 不同点就在于这道题的目标值不是你输入的,而每个数都可以作为目标值,这道题中“其中有多少个数,恰好等于集合中另外两个(不同的)数之和”这句话特别关键,我第一次就错在了这,不同的2个数对相加都等于目标值的话,只能算1个答案(在{1,2,3,4,5}中,1+4=5,2+3=5,结果只算1个)所以为了提升速度,在找到第一个结果后立马重新选择目标值,过程中进行计数即可。

3.代码如下:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	int n, sum = 0;	
	int a[100];
	scanf_s("%d", &n);
	for (int i = 0; i < n; i++)			/* 录入数据 */
		scanf_s("%d", &a[i]);
	for (int i = 0; i < n; i++)			/* 目标值循环 */
	{
		for (int j = 0; j < n - 1; j++)		/* 被加数循环 */
		{
			for (int z = j + 1; z < n; z++)	/* 加数循环 */
			{
				if (a[j] + a[z] == a[i]) /* 判断加数与被加数是否为目标值 */
				{
					sum++;				/* 条件成立后,答案+1 */
					goto end;			/* 找到结果后立马退出2个for循环,重新选择目标值 */
				}
			}
		}
	end:;
	}
	printf("%d", sum);
	return 0;
}

三、压缩技术

设某汉字由N × N的0和1的点阵图案组成。
我们依照以下规则生成压缩码。连续一组数值:从汉字点阵图案的第一行第一个符号开始计算,按书写顺序从左到右,由上至下。第一个数表示连续有几个0,第二个数表示接下来连续有几个1,第三个数再接下来连续有几个0,第四个数接着连续几个1,以此类推……
例如: 以下汉字点阵图案:
0001000
0001000
0001111
0001000
0001000
0001000
1111111
对应的压缩码是: 7 3 1 6 1 6 4 3 1 6 1 6 1 3 7 (第一个数是N ,其余各位表示交替表示0和1 的个数,压缩码保证 N × N=交替的各位数之和)

输入格式:
一行,压缩码。
输出格式:
汉字点阵图(点阵符号之间不留空格)。(3<=N<=200)

1.样例

> 输入:
7 3 1 6 1 6 4 3 1 6 1 6 1 3 7
> 输出:
0001000
0001000
0001111
0001000
0001000
0001000
1111111

2.做题思路

一开始容易想到为二维数组的应用,但是发现自己无法实现,所以就想到了将一维数组按照需要格式输出,按照所给的压缩码,将一维数组按照顺序初始化,然后按照格式输出就可以了。详细请看代码。

3.代码如下:

#include <stdio.h>
#include <stdlib.h>
#define LEN 40000		/* 宏定义长度 */
int main()
{
	static int a[LEN], b[LEN];
	int n, sum = 0;
	int i, j;
	i = j = 0;
	scanf_s("%d", &n);		/* 第一个数N */
	while (sum != n * n)	/* 录入数之和等于矩阵N*N时录入结束 */
	{
		scanf_s("%d", &b[i]);
		sum += b[i];
		i++;
	}
	int lenth = i;			/* lenth为录入数的数量 */
	int x = 0;
	for (i = 0; i < lenth; i++) /* 0和1的交错赋值次数 */
	{
		for (j = 0; j < b[i]; j++) /* 0和1交错赋值 */
		{
			if (i % 2 == 0) a[x] = 0;
			else a[x] = 1;
			x++;			/* 记录次数实现交错 */
		}
	}
	x = 0;
	for (i = 0; i < n; i++)		/* 共n行 */
	{
		for (j = 0; j < n; j++) /* 每n个为一行 */
		{
			printf("%d", a[x]);
			x++;
		}
		printf("\n");
	}
	return 0;
}

四、显示器

液晶屏上,每个阿拉伯数字都是可以显示成 3×5 的点阵的(其中 X 表示亮点,. 表示暗点)。现在给出数字位数(不超过 100)和一串数字,要求输出这些数字在显示屏上的效果。数字的显示方式如同样例输出,注意每个数字之间都有一列间隔。

1.样例

>输入:
10
0123456789
>输出:
XXX...X.XXX.XXX.X.X.XXX.XXX.XXX.XXX.XXX
X.X...X...X...X.X.X.X...X.....X.X.X.X.X
X.X...X.XXX.XXX.XXX.XXX.XXX...X.XXX.XXX
X.X...X.X.....X...X...X.X.X...X.X.X...X
XXX...X.XXX.XXX...X.XXX.XXX...X.XXX.XXX

2.做题思路

肯定会想到二维数组吧,的确,就是二维数组,个人觉得这道题主要考了我字符串的应用😂,写完发现这道题没什么难度,难的就是不敢那么想。个人做法有些神奇。

3.代码如下:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
	static char a[101];
	static char ch[5][1000];
	int n;
	scanf_s("%d", &n);
	scanf_s("%s", a, n + 1);	/* 录入需要在显示器上显示的数字 */
	for (int i = 0; i < n ; i++)
	{
		int j = 4 * (i + 1) - 3;	/* 设置每个字符串的起始地址,使得字符串不重叠 */
		if (a[i] == '0')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "X.X.");
			strcpy_s(&ch[2][j], 5, "X.X.");
			strcpy_s(&ch[3][j], 5, "X.X.");
			strcpy_s(&ch[4][j], 5, "XXX.");
		}
		else if (a[i] == '1')
		{
			strcpy_s(&ch[0][j], 5, "..X.");
			strcpy_s(&ch[1][j], 5, "..X.");
			strcpy_s(&ch[2][j], 5, "..X.");
			strcpy_s(&ch[3][j], 5, "..X.");
			strcpy_s(&ch[4][j], 5, "..X.");
		}
		else if (a[i] == '2')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "..X.");
			strcpy_s(&ch[2][j], 5, "XXX.");
			strcpy_s(&ch[3][j], 5, "X...");
			strcpy_s(&ch[4][j], 5, "XXX.");
		}
		else if (a[i] == '3')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "..X.");
			strcpy_s(&ch[2][j], 5, "XXX.");
			strcpy_s(&ch[3][j], 5, "..X.");
			strcpy_s(&ch[4][j], 5, "XXX.");
		}
		else if (a[i] == '4')
		{
			strcpy_s(&ch[0][j], 5, "X.X.");
			strcpy_s(&ch[1][j], 5, "X.X.");
			strcpy_s(&ch[2][j], 5, "XXX.");
			strcpy_s(&ch[3][j], 5, "..X.");
			strcpy_s(&ch[4][j], 5, "..X.");
		}
		else if (a[i] == '5')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "X...");
			strcpy_s(&ch[2][j], 5, "XXX.");
			strcpy_s(&ch[3][j], 5, "..X.");
			strcpy_s(&ch[4][j], 5, "XXX.");
		}
		else if (a[i] == '6')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "X...");
			strcpy_s(&ch[2][j], 5, "XXX.");
			strcpy_s(&ch[3][j], 5, "X.X.");
			strcpy_s(&ch[4][j], 5, "XXX.");
		}
		else if (a[i] == '7')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "..X.");
			strcpy_s(&ch[2][j], 5, "..X.");
			strcpy_s(&ch[3][j], 5, "..X.");
			strcpy_s(&ch[4][j], 5, "..X.");
		}
		else if (a[i] == '8')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "X.X.");
			strcpy_s(&ch[2][j], 5, "XXX.");
			strcpy_s(&ch[3][j], 5, "X.X.");
			strcpy_s(&ch[4][j], 5, "XXX.");
		}
		else if (a[i] == '9')
		{
			strcpy_s(&ch[0][j], 5, "XXX.");
			strcpy_s(&ch[1][j], 5, "X.X.");
			strcpy_s(&ch[2][j], 5, "XXX.");
			strcpy_s(&ch[3][j], 5, "..X.");
			strcpy_s(&ch[4][j], 5, "XXX.");
		}
	}
	for (int i = 0; i < 5; i++)		/* 共有5行 */
	{
		ch[i][strlen(&ch[i][1])] = '\0';	/* 最后一行的时候要把多余的.删掉 */
		printf("%s\n", &ch[i][1]);		/* 输出本行字符串 */
	}
	return 0;
}

在查看其他题解的过程中,我惊奇的发现了一个代码很短的一个答案,各位也可以学习一下。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
const char l[50][50] =
{
    {"XXX\0..X\0XXX\0XXX\0X.X\0XXX\0XXX\0XXX\0XXX\0XXX\0"}, \
    {"X.X\0..X\0..X\0..X\0X.X\0X..\0X..\0..X\0X.X\0X.X\0"}, \
    {"X.X\0..X\0XXX\0XXX\0XXX\0XXX\0XXX\0..X\0XXX\0XXX\0"}, \
    {"X.X\0..X\0X..\0..X\0..X\0..X\0X.X\0..X\0X.X\0..X\0"}, \
    {"XXX\0..X\0XXX\0XXX\0..X\0XXX\0XXX\0..X\0XXX\0XXX\0"}
};
int main()
{
    int i, j, n;
    char x[100];
    scanf_s("%d\n", &n);
    for (i = 0; i < n; i++) scanf_s("%c", x + i, 1);
	for (i = 0; i < 5; i++)
	{
        for (j = 0; j < n; j++)
        {
            printf("%s", l[i] + (x[j] - 48) * 4);
            if (j < n - 1) putchar('.');
        }
        putchar('\n');
    }
    return 0;
}

总结

上面的题都考察了数组和循环语句的使用,这些题型就是为了锻炼让代码跟着思维走,上面的代码都是自己根据思维写的,在洛谷上也全部通过了,速度和代码长度也相对好一些,欢迎点评😀

  • 在洛谷测试需要修改strcpy_s,scanf_s函数,上述代码在VS2019中可正常运行,如果不修改上述函数,可能会编译错误。字符串修改可查看VS2019中部分字符串函数的使用
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值