2021年12月青少年C语言(三级)等级考试试卷及答案

文章介绍了几个编程问题,包括计算门牌号问题(使用递推法),统计01字符串子串出现次数,设计吃糖果方案的递推算法,以及绘制分形盒的递归方法。每个问题都涉及到了IT技术中的算法设计和数学逻辑应用。
摘要由CSDN通过智能技术生成

目录

1 我家的门牌号

2 字串计算

3 吃糖果

4 拨钟问题

5 方形盒


1 我家的门牌号


时间限制:1000

内存限制:65536

我家住在一条短胡同里,这条胡同的门牌号从1开始顺序编号。若所有的门牌号之和减去我家门牌号的两倍,恰好等于n,求我家的门牌号及总共有多少家。数据保证有唯一解。

输入

一个正整数n。n < 100000。

输出

一行,包含两个正整数,分别是我家的门牌号及总共有多少家,中间用单个空格隔开。

样例输入

100


样例输出

10 15

解析:用for循环对门牌号逐个尝试,详情看code

#include <bits/stdc++.h>
using namespace std;
int main(){
	int n,home,x,i;
	cin>>n;//题目要求,输入n
	for(i=1;;i++){//从家的门牌号逐个尝试
		if((i*i+i-2*n)%4==0){
			x=(i*i+i-2*n)/4;
			if(x<=0)	continue;//x不可能小于一
			if(x>0){//找到后
				cout<<x<<" "<<i;//输出结果
				return 0;//终止循环
			}
		}
	}
	system("color 6");
	return 0;
}

2 字串计算


时间限制:1000

内存限制:65536

给出一个只包含0和1的字符串(长度在1到100之间),求其每一个子串出现的次数。

输入

一行,一个01字符串。

输出

对所有出现次数在1次以上的子串,输出该子串及出现次数,中间用单个空格隔开。按子串的字典序从小到大依次输出,每行一个。

样例输入

10101

样例输出

0 2
01 2
1 3
10 2
101 2
#include <bits/stdc++.h>
using namespace std;
int main(){
	string str;
	map <string, int> mp; 
	while(cin >> str){
		for(int i = 1 ;i <= str.size(); i ++){   
			for(int j = 0; j < i; j ++){
				string sub_str = str.substr(j , i - j);
				mp[sub_str] ++;
			}
		}
		map<string, int> :: iterator it = mp.begin();
		for(it ; it != mp.end() ; it++){
			if(it -> second > 1){
				cout << it -> first << " " << it -> second << endl;
			}
		}
		mp.clear();
	} 
	system("color 6");
	return 0;
}

3 吃糖果


时间限制:1000

内存限制:65536

名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0)。妈妈告诉名名每天可以吃一块或者两块巧克力。假设名名每天都吃巧克力,问名名共有多少种不同的吃完巧克力的方案。例如:如果N=1,则名名第1天就吃掉它,共有1种方案;如果N=2,则名名可以第1天吃1块,第2天吃1块,也可以第1天吃2块,共有2种方案;如果N=3,则名名第1天可以吃1块,剩2块,也可以第1天吃2块剩1块,所以名名共有2+1=3种方案;如果N=4,则名名可以第1天吃1块,剩3块,也可以第1天吃2块,剩2块,共有3+2=5种方案。现在给定N,请你写程序求出名名吃巧克力的方案数目。

输入

输入只有1行,即整数N。

输出

输出只有1行,即名名吃巧克力的方案数。

样例输入

4

样例输出

5

解析:递推, 在吃掉第i块糖果时,可以在吃掉i-1块糖果后一天吃一块,也可以在吃掉i-2块糖果后一天吃掉两块,即a[i]=a[i-1]+a[i-2],循环递推即可。

该题的问题是问有多少种不同的吃完巧克力的方案,而不是需要多少天的问题,所以天数只起迷惑作用。
我们假设盒内有1块巧克力,每次吃1或2块,求方法数;假设有2块巧克力,每次吃1或2块,求方法数;假设有3块巧克力,每次吃1或2块…类比下去会发现这个题就是走台阶问题(对于走台阶问题应该是比较熟悉的),巧克力数就是台阶数,每次能迈1或2阶,因此可得递推式: f(n) = f(n-1)+f(n-2)

详见代码: 

#include <bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	int a[100]={0};
	a[1]=1;
	a[0]=1;
	for(int i=2;i<=n;i++){
		a[i]=a[i-1]+a[i-2];
	}
	cout<<a[n];
	system("color 6");
	return 0;
}

4 拨钟问题


拨钟问题

有9个时钟,排成一个3*3的矩阵。

现在需要用最少的移动,将9个时钟的指针都拨到12点的位置。共允许有9种不同的移动。如下表所示,每个移动会将若干个时钟的指针沿顺时针方向拨动90度。

移动 影响的时钟

1 ABDE

2 ABC

3 BCEF

4 ADG

5 BDEFH

6 CFI

7 DEGH

8 GHI

9 EFHI

输入

9个整数,表示各时钟指针的起始位置,相邻两个整数之间用单个空格隔开。其中,0=12点、1=3点、2=6点、3=9点。

输出

输出一个最短的移动序列,使得9个时钟的指针都指向12点。按照移动的序号从小到大输出结果。相邻两个整数之间用单个空格隔开。(数据保证答案唯一)

样例输入

3 3 0
2 2 2
2 1 2


样例输出

4 5 8 9
/*
9个操作,每个操作最多做3次
因为超过3次之后就回到原位置了。
所以可以9个for循环枚举每个操作
设置i[10]数组,i[1]~i[9]代表1到9这个操作
A始终受操作1,2,4的影响
时钟初始保存在数组mp[9]里
那么mp[1]的变化就是mp[1]+i[1]+i[2]+i[4]在对4取余
其余时钟变化也可以顺势表示出来
全部加起来求和如果等于0就全部归位了
全部等于0只能是9个0加起来没有别的情况因为不存在负数
*/
#include <bits/stdc++.h>
using namespace std;
int n,mp[10],i[10];
int main(){
	for(int i=1;i<=9;i++){
		cin>>mp[i];
	}
	for(i[1]=0;i[1]<4;i[1]++){
		for(i[2]=0;i[2]<4;i[2]++){
			for(i[3]=0;i[3]<4;i[3]++){
				for(i[4]=0;i[4]<4;i[4]++){
					for(i[5]=0;i[5]<4;i[5]++){
						for(i[6]=0;i[6]<4;i[6]++){
							for(i[7]=0;i[7]<4;i[7]++){
								for(i[8]=0;i[8]<4;i[8]++){
									for(i[9]=0;i[9]<4;i[9]++){
										int sum=0;
										sum+=(mp[1]+i[1]+i[2]+i[4])%4;/* 时钟A受操作1和2和                
                                        4的影响其余同理*/
										sum+=(mp[2]+i[1]+i[2]+i[3]+i[5])%4;
										sum+=(mp[3]+i[2]+i[3]+i[6])%4;
										sum+=(mp[4]+i[1]+i[4]+i[5]+i[7])%4;
										sum+=(mp[5]+i[1]+i[3]+i[5]+i[7]+i[9])%4;
										sum+=(mp[6]+i[3]+i[5]+i[6]+i[9])%4;
										sum+=(mp[7]+i[4]+i[7]+i[8])%4;
										sum+=(mp[8]+i[5]+i[7]+i[8]+i[9])%4;
										sum+=(mp[9]+i[6]+i[8]+i[9])%4;
										if(sum==0){
											for(int x=1;x<=9;x++){
												if(i[x]--)
													cout<<x<<" ";
											}
											return 0;
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	system("color 6");
	return 0;
}

5 方形盒


时间限制:1000

内存限制:65536

分形,通常被定义为一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状,即具有自相似的性质。它跟分数维、自组织、非线性系统和混沌等具有非常重要的联系。分形盒就是这样一种分形,它的定义如下:

维度是1的分形盒:

X

维度是2的分形盒:

X  X

  X

X  X

如果已知维度是(n-1)的分形盒,那么维度是n的分形盒的递归定义如下所示:

Box(n-1)               Box(n-1)

              Box(n-1)

Box(n-1)               Box(n-1)   

你的任务是画一个维度为n的分形盒。

输入

输入包含多组测试数据。每一行包含一个正整数n表示分形盒的维度,n不大于7;最后一行是一个-1,表示输入结束。

输出

对于每组测试数据,输出要求维度的分形盒,注意X为大写字母。每组测试数据之后包含一行,改行只包含一个破折号。

样例输入

1
2
3
4
-1

样例输出:

X
-
X X
 X
X X
-
X X   X X
 X     X
X X   X X
   X X
    X
   X X
X X   X X
 X     X
X X   X X
-
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
   X X               X X
    X                 X
   X X               X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
         X X   X X
          X     X
         X X   X X
            X X
             X
            X X
         X X   X X
          X     X
         X X   X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
   X X               X X
    X                 X
   X X               X X
X X   X X         X X   X X
 X     X           X     X
X X   X X         X X   X X
-

详见代码:

//这道题我用的是递归,还有更好的思路欢迎评论区留言!
#include <bits/stdc++.h>
using namespace std;
char a[2200][2200];
void draw(int x,int y,int n){//左上角为x,y,画一个层数为n的分型盒
	if(n==0){
		a[x][y]='x';
		return;
	}
	draw(x,y,n-1); //左上
    draw(x,y+2*pow(3,n-1),n-1);//右上
    draw(x+2*pow(3,n-1), y, n-1); //左下
    draw(x+2*pow(3,n-1), y+2*pow(3,n-1), n-1); //右下
    draw(x+pow(3,n-1), y+pow(3,n-1), n-1);//中
}
int main(){
	int n;
	while(1){
        memset(a,0,sizeof(0));//将数值0以单个字节逐个拷贝的方式放到指针变量a所指的内存中去。

        cin>>n;
        if(n==-1) break;
        draw(1,1,n-1);//调用
        for(int i = 1; i <= pow(3,n-1); i++){
            for(int j = 1; j <= pow(3,n-1); j++){
                if(a[i][j]==0) cout<<" ";
                else cout<<"X";
            }
            cout<<endl;
        }
        cout<<"-"<<endl;
    }
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值