信息学奥赛初赛天天练-55-CSP-J2019完善程序1-位运算左移、右移、布尔变量的值、递归算法
PDF文档公众号回复关键字:20240804
![](https://img2022.cnblogs.com/blog/404484/202211/404484-20221123185906168-1425738362.png)
1 完善程序 (单选题 ,每小题3分,共30分)
1.(矩阵变幻)有一个奇幻的矩阵,在不停的变幻,其变幻方式为:
数字 0 变成矩阵
0 0
0 1
数字 1 变成矩阵
1 1
1 0
最初该矩阵只有一个元素 0,变幻 n 次后,矩阵会变成什么样?
例如,矩阵最初为:[0];
矩阵变幻 1次后:
0 0
0 1
矩阵变幻 2 次后:
0 0 0 0
0 1 0 1
0 0 1 1
0 1 1 0
输入一行一个不超过 10 的正整数 n。输出变幻 n 次后的矩阵。
试补全程序。
提示:
<<
表示二进制左移运算符,例如 (11)2 <<
2=(1100)2;
而 ^
表示二进制异或运算符,它将两个参与运算的数中的每个对应的二进制位—进行比较,若两个二进制位相同,则运算结果的对应二进制位为 0 ,反之为 1。
01 #include <cstdio>
02 using namespace std;
03 int n;
04 const int max_size = 1 << 10;
05
06 int res[max_size][max_size];
07
08 void recursive(int x, int y, int n, int t) {
09 if (n == 0) {
10 res[x][y] = ①;
11 return;
12 }
13 int step = 1 << (n - 1);
14 recursive(②, n - 1, t);
15 recursive(x, y + step, n - 1, t);
16 recursive(x + step, y, n - 1, t);
17 recursive(③, n - 1, !t);
18 }
19
20 int main() {
21 scanf("%d", &n);
22 recursive(0, 0, ④);
23 int size = ⑤;
24 for (int i = 0; i < size; i++) {
25 for (int j = 0; j < size; j++)
26 printf("%d ", res[i][j]);
27 puts(" ");
28 }
29 return 0;
30 }
1 ①处应填( ) [3分]
A n%2
B 0
C t
D 1
2 ②处应填( ) [3分]
A x-step,y-step
B x,y-step
C x-step,y
D x,y
3 ③处应填( ) [3分]
A x-step,y-step
B x+step,y+step
C x-step,y
D x,y-step
4 ④处应填( ) [3分]
A n-1,n%2
B n,0
C n,n%2
D n-1,0
5 ⑤处应填( ) [3分]
A 1<<(n+1)
B 1<<n
C n+1
D 1<<(n-1)
2 相关知识点
1) 位运算
左移(<<)、右移(>>)
左移
左移1位,所有位都左移,末尾补0
右移
右移1位,所有位都右移,首尾补0
//左移 << 右移 >>
#include<bits/stdc++.h>
using namespace std;
int main(){
int a=3;
/*
3 对应二进制
0000 0011
左移1位,所有位都左移,末尾补0
0000 0110
此时对应二进制转十进制为6
*/
int b=3<<1;
cout<<"b的值为:"<<b<<endl;//所以b的值为6
int c=8;
/*
8 对应二进制
0000 1000
右移1位,所有位都右移,首尾补0
0000 0100
此时对应二进制转十进制为4
*/
int d=c>>1;
cout<<"d的值为:"<<d;//所以d的值为4
return 0;
}
2) 布尔变量
bool是占一个字节的逻辑值,定义出来的变量只有true
和false
两个,分别表示真和假,对应1
和0
两个值
#include <iostream>
using namespace std;
int main(){
bool bl=false;
cout<<bl<<endl;//输出0
bl=true;
cout<<bl<<endl;//输出1
bl=0;
cout<<bl<<endl;//输出0
bl=5;//赋值大于0的数,则为1
cout<<bl<<endl;//输出1
bl=-1;//赋值不为0的数,则为1
cout<<bl<<endl;
bl=!bl;//! 通过非运算 对bl值改变 1变0
cout<<bl;
return 0;
}
3) 递归
递归是一种解决问题的方法,它通过将问题分解为更小的子问题来解决。
一个递归函数会在其定义中直接或间接地调用自身
递归通常包括两个部分:基本情况(Base case)和递归步骤(Recursive step)。
基本情况是指当问题规模变得足够小时,可以直接得到解决方案的情况。
调用1次recursive 函数,会递归调用4次,每次输出recursive的值
考虑最后1次,n=1时,t=1时,分别在对应位置输出0,0,0,1
n=2时,也会有4种情况,每种情况输出4个值
具体可以看下面详细分析
08 void recursive(int x, int y, int n, int t) {
09 if (n == 0) {
10 res[x][y] = t;
11 return;
12 }
13 int step = 1 << (n - 1);
14 recursive(x,y, n - 1, t);
15 recursive(x, y + step, n - 1, t);
16 recursive(x + step, y, n - 1, t);
17 recursive(x+step,y+step, n - 1, !t);
18 }
3 思路分析
大致思路
每次从当前,右边,左下,右下4个方向填数,并且遵循当前,右边,左下填的数相同,右下填的数相反
例如
变换1次
变换2次
变换3次
1 ①处应填( C ) [3分]
A n%2
B 0
C t
D 1
分析
从整体程序看,变换主要时0变1,1变0
从下图和下面程序可知,填的数只有t和!t,而逻辑表达式,只有0和1这2种,所以此处填t
14 recursive(②, n - 1, t);
15 recursive(x, y + step, n - 1, t);
16 recursive(x + step, y, n - 1, t);
17 recursive(③, n - 1, !t);
例如
0 变换时,3个t和1个!t
变换成3个0和1个1
1 变换时,3个t和1个!t
变换成3个1和1个0
2 ②处应填( D ) [3分]
A x-step,y-step
B x,y-step
C x-step,y
D x,y
分析
从变换如下程序和变换图形可知,是把当前数变换成4个数,其位置为当前,右,左下,右下
如下程序已经给出了右和左下
而选项中没有给出右下,只能选当,对应的是前x和y
14 recursive(②, n - 1, t);
15 recursive(x, y + step, n - 1, t);
16 recursive(x + step, y, n - 1, t);
17 recursive(③, n - 1, !t);
3 ③处应填( B ) [3分]
A x-step,y-step
B x+step,y+step
C x-step,y
D x,y-step
分析
从变换如下程序和变换图形可知,是把当前数变换成4个数,其位置为当前,右,左下,右下
如下程序已经给出了右和左下
而当前已经被②使用,所以只剩下右下了,对应x+step,y+step
14 recursive(②, n - 1, t);
15 recursive(x, y + step, n - 1, t);
16 recursive(x + step, y, n - 1, t);
17 recursive(③, n - 1, !t);
4 ④处应填( B ) [3分]
A n-1,n%2
B n,0
C n,n%2
D n-1,0
分析
08 void recursive(int x, int y, int n, int t) {
22 recursive(0, 0, ④);
从上面程序可以看出, ④需要填n和t这2个参数
需要经过n次变换,所以此处填n
第1次变换从0开始,所以t为0
5 ⑤处应填( B ) [3分]
A 1<<(n+1)
B 1<<n
C n+1
D 1<<(n-1)
分析
1次变换生成2行2列 2^1
2次变换生成4行4列 2^2
...
n次变换生成2^n行,2^n列
而 1<<n 对应的值和2^n相同
作者:newcode 更多资源请关注纽扣编程微信公众号
从事机器人比赛、机器人等级考试、少儿scratch编程、信息学奥赛等研究学习