简介

本页仅为记录个人学习记录

001排列组合

题目:有 1、2、3、4 四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?

程序分析:可填在百位、十位、个位的数字都是 1、2、3、4,组成所有的排列后再去掉不满足条件的排列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
int main()
{
int i,j,k;
printf("\n");
for(i=1;i<5;i++) { // 以下为三重循环
for(j=1;j<5;j++) {
for (k=1;k<5;k++) { // 确保i、j、k三位互不相同
if (i!=k&&i!=j&&j!=k) {
printf("%d,%d,%d\n",i,j,k);
}
}
}
}
}

002结构体实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

struct programming
{
float constant;
char *pointer;
};

int main()
{
struct programming variable;
char string[] = "sheep's blog";

variable.constant = 1.23;
variable.pointer = string;

printf("%f\n", variable.constant);
printf("%s\n", variable.pointer);

return 0;
}

运行结果:

230000 
sheep's blog

003判断素数

  1. 只判断是否是素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

int main() {
int a;
printf("请输入一个自然数:");
scanf("%d", &a);

if (a <= 1) {
printf("该数不是素数(素数必须大于1)。\n");
return 0;
}

int is_prime = 1;
for (int i = 2; i < a; i++) {
if (a % i == 0) {
is_prime = 0;
break;
}
}

if (is_prime) {
printf("该数是素数。\n");
} else {
printf("该数不是素数。\n");
}

return 0;
}
  1. 如果此时想要在两个自然数之间寻找素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
int main() {
int a, b;

printf("请输入两个自然数(用空格分隔):");
scanf("%d %d", &a, &b);

printf("%d 和 %d 之间有素数:", a, b);

for (; a <= b; a++) {
int count = 0; // 每次判断一个数是否为素数时,重置为0
if (a < 2) continue; // 1 不是素数,小于2的直接跳过

for (int i = 2; i < a; i++) {
if (a % i == 0) {
count = 1;
break;
}
}

if (count == 0) {
printf("%d ", a);
}
}

printf("\n");
return 0;
}

从 2 到 a-1 一个个试除。这没问题,适合学习,但效率不高,尤其是当数字较大时,所以我们可以优化一下

优化方法:​​

  • 只需试除到 sqrt(a)即可,因为如果 a有大于 sqrt(a)的因子,那必然对应一个小于 sqrt(a)的因子。

  • 可以改成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <math.h>

int is_prime(int num) {
if (num < 2) return 0;
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) return 0;
}
return 1;
}

int main() {
int a, b;
printf("请输入两个自然数:");
scanf("%d %d", &a, &b);

printf("%d 和 %d 之间有素数:", a, b);
for (; a <= b; a++) {
if (is_prime(a)) {
printf("%d ", a);
}
}
printf("\n");
return 0;
}

这个版本把素数判断封装成一个函数 is_prime(),代码更清晰、可读性更高,同时只试除到 sqrt(num),效率更高。

004象棋

题目描述

你正在帮助他们设计一款象棋软件。现在,你想要设计一个逻辑功能。以下是对这个功能的介绍。

想象一个无限大的棋盘,我们用 $(x, y)$ 表示棋盘的第 $x$ 行第 $y$ 列。具体的,如果说一个棋子在 $(x, y)$ 位置,那么这个棋子则在棋盘的第 $x$ 行第 $y$ 列。

现在有四种棋子车、炮、马、象。它们对应的编号及它们的吃棋子规则如下表所示。以下规则均假设当前棋子在 $(x, y)$ 位置。

请注意,以下规则可能与真实的中国象棋规则略有不同。

名称 编号 走法规则
$1$ 可沿横线或者竖线移动,即一次操作可以吃掉 $(x + k, y), (x - k, y), (x, y + k), (x, y - k)$ 中的任意一个位置的棋子($k$ 为任意正整数)。
$2$ 想象一条直线,炮与对方棋子都在这条直线上。那么只有在这条直线上的炮与对方棋子的中间有一个另外的棋子时,炮才能吃掉对方。
$3$ 马走日,即一次操作可以吃掉 $(x + 2, y + 1), (x + 2, y - 1), (x - 2, y + 1), (x - 2, y - 1), (x + 1, y + 2), (x + 1, y - 2), (x - 1, y + 2), (x - 1, y - 2)$ 中的任意一个位置的棋子。
$4$ 象走田,即一次操作可以吃掉 $(x + 2, y + 2), (x + 2, y - 2), (x - 2, y + 2), (x - 2, y - 2)$ 中的任何一个位置的棋子。

现在你得到了一组询问,包含 $p, x _ 0, y _ 0, x _ 1, y _ 1$ 五个整数,代表现在棋盘上只有两个棋子,第一个棋子编号为 $p$,在第 $x _ 0$ 行,第 $y _ 0$ 列。第二个棋子编号未知且不需要了解,在第 $x _ 1$ 行,第 $y _ 1$ 列。

你需要考虑,如果你现在可以且仅可以操作第一个棋子一次,第一个棋子能否吃掉第二个棋子。

输入格式

输入共一行。

第一行为五个整数 $p, x _ 0, y _ 0, x _ 1, y _ 1$,两两之间以一个空格隔开,同题面中的含义。

输出格式

输出一行,如果第一个棋子可以吃掉第二个棋子,输出 Yes,否则输出 No

输入输出样例 #1

输入 #1

1
1 1 4 2 4

输出 #1

1
Yes

输入输出样例 #2

输入 #2

1
1 1 4 2 5

输出 #2

1
No

输入输出样例 #3

输入 #3

1
2 1 1 2 1

输出 #3

1
No

输入输出样例 #4

输入 #4

1
3 1 4 2 6

输出 #4

1
Yes

说明/提示

样例解释

样例组 #1 与 #2 代表了车能够与不能够吃掉对方棋子的情况。

样例组 #3 代表了炮不能够吃掉对方棋子的情况。

样例组 #4 代表了马能够吃掉对方棋子的情况。

https://www.luogu.com.cn/paste/et767k4o 中含有所有样例的棋子摆放情况,可以按需查阅。

数据规模与约定

对于 $20%$ 的数据,保证 $p = 2$;
对于 $100%$ 的数据,保证 $p \in {1, 2, 3, 4}$,$1 \leq x _ 0, y _ 0, x _ 1, y _ 1 \leq 10 ^ 9$,且保证不存在 $x _ 0$ 与 $x _ 1$、$y _ 0$ 与 $y _ 1$ 同时相等的情况,即两个棋子不会重合。

以上来自于洛谷B3707

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <stdio.h>

int main() {
int p, x0, y0, x1, y1;
// 读取输入:棋子编号、两个棋子的坐标
scanf("%d %d %d %d %d", &p, &x0, &y0, &x1, &y1);

// 计算x轴差的绝对值(自行实现,无需abs)
int dx = x1 - x0;
if (dx < 0) dx = -dx;
// 计算y轴差的绝对值
int dy = y1 - y0;
if (dy < 0) dy = -dy;

// 根据棋子类型判断能否吃子
if (p == 1) { // 车:同列或同行
if (x0 == x1 || y0 == y1) {
printf("Yes");
} else {
printf("No");
}
} else if (p == 2) { // 炮:无其他棋子,无法吃子
printf("No");
} else if (p == 3) { // 马:日字走法
if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2)) {
printf("Yes");
} else {
printf("No");
}
} else if (p == 4) { // 象:田字走法
if (dx == 2 && dy == 2) {
printf("Yes");
} else {
printf("No");
}
}

return 0;
}

这是第一版,但代码量偏大于是想起来库函数 <stdlib.h>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <stdlib.h> // 用于abs函数计算绝对值

int main() {
int p, x0, y0, x1, y1;
// 读取输入
scanf("%d %d %d %d %d", &p, &x0, &y0, &x1, &y1);

// 计算坐标差的绝对值
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);

if (p == 1) { // 车:同列或同行
if (x0 == x1 || y0 == y1) {
printf("Yes");
} else {
printf("No");
}
} else if (p == 2) { // 炮:无其他棋子,无法吃子
printf("No");
} else if (p == 3) { // 马:日字走法
if ((dx == 2 && dy == 1) || (dx == 1 && dy == 2)) {
printf("Yes");
} else {
printf("N");
}
} else if (p == 4) { // 象:田字走法
if (dx == 2 && dy == 2) {
printf("Yes");
} else {
printf("No");
}
}

return 0;
}