C/C++ 第十一届蓝桥杯大赛校内模拟 题解

题目类型
15.125GB结果填空
约数个数结果填空
叶结点数结果填空
数字9结果填空
数位递增的数编程题
递增三元组编程题
音节判断编程题
长草编程题
序列计数编程题
晚会节目单编程题

1. 15.125GB

  • 问题描述
    在计算机存储中,15.125GB是多少MB?
  • 答案提交
    这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

  • 解析
    1GB=1024MB
    因此,15.125GB=15.125×1024MB=15488MB
  • 答案
    15488

2. 约数个数

  • 问题描述
    1200000有多少个约数(只计算正约数)
  • 答案提交
    这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

  • 解析
    #include<iostream>
    using namespace std;
    int main()
    {
    	int ans = 0;
    	for (int i = 1; i <= 1200000; i++)
    	{
    		if (1200000 % i == 0) ans++;
    	}
    	cout << ans;
    	return 0;
    }
    
  • 答案
    96

3. 叶结点数

  • 问题描述
    一棵包含有2019个结点的二叉树,最多包含多少个叶结点?
  • 答案提交
    这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

  • 解析
    ①公式法
    由二叉树的性质可知: n = n0 + n1 + n2,而 n0 = n2 + 1,两式合并,得 n = 2n0 + n1 - 1
    为了使叶子节点数(n0)最多,那么 n1 就得最小,设为0,n0 = (n + 1) / 2
    因此,(2019 + 1) / 2 = 1010
    引用:https://blog.csdn.net/weixin_46239370/article/details/105928843

    ②画图
    叶结点:不具有子结点的结点。
    第1层有20=1个结点
    第2层有21=2个结点

    第10层有29=512个结点
    以上10层共有20+21+…+29=1023个结点,其中第10层均为叶结点,有29=512个。
    在第10层的基础上,若第10层的结点均有2个叶结点,则到第11层有210=1024个结点,而此时20+21+…+29+210=2047>2019
    因此,第11层并非全满的结点。
    于是在第10层时,还差2019-1023=996个结点。
    而1个结点可分出2个叶结点,因此在第10层的每个结点的基础上,新增第11层的996个结点,此时第10层消耗了996/2=498个结点。
    因此,第10层还剩下512-498=14个结点。故共有996+14=1010个叶结点

  • 答案
    1010


4. 数字9

  • 问题描述
    在1至2019中,有多少个数的数位中包含数字9?
    注意,有的数中的数位中包含多个9,这个数只算一次。例如,1999这个数包含数字9,在计算只是算一个数。
  • 答案提交
    这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

  • 解析
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
    	int ans = 0; //记录答案
    	for (int i = 1; i <= 2019; i++)
    	{
    		string s = to_string(i); //转换为字符串,便于遍历该数字
    		for (int j = 0; j < s.length(); j++)
    		{
    			//如果有9在数字中,则ans+1,并且退出遍历循环
    			if (s[j] == '9')
    			{
    				ans++;
    				break;
    			}
    		}
    	}
    	cout << ans;
    	return 0;
    }
    
  • 答案
    544

5. 数位递增的数

  • 问题描述
    一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。
    给定正整数 n,请问在整数 1 至 n 中有多少个数位递增的数?
  • 输入格式
    输入的第一行包含一个整数 n。
  • 输出格式
    输出一行包含一个整数,表示答案。
  • 样例输入
    30
  • 样例输出
    26
  • 评测用例规模与约定
    对于 40% 的评测用例,1 <= n <= 1000。
    对于 80% 的评测用例,1 <= n <= 100000。
    对于所有评测用例,1 <= n <= 1000000。

  • 答案
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
    	int n, ans = 0;
    	cin >> n;
    	for (int i = 1; i <= n; i++)
    	{
    		string s = to_string(i);//转换为字符串,便于遍历该数字
    		bool flag = true;
    		for (int j = 0; j < s.length() - 1; j++)
    		{
    			//不满足条件,则flag标记为false,并且退出循环,遍历下一数字
    			if (s[j] > s[j + 1])
    			{
    				flag = false;
    				break;
    			}
    		}
    		if (flag) ans++;
    	}
    	cout << ans;
    	return 0;
    }
    

6. 递增三元组

  • 问题描述
    在数列 a[1], a[2], …, a[n] 中,如果对于下标 i, j, k 满足 0<i<j<k<n+1 且 a[i]<a[j]<a[k],则称 a[i], a[j], a[k] 为一组递增三元组,a[j]为递增三元组的中心。
    给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。
  • 输入格式
    输入的第一行包含一个整数 n。
    第二行包含 n 个整数 a[1], a[2], …, a[n],相邻的整数间用空格分隔,表示给定的数列。
  • 输出格式
    输出一行包含一个整数,表示答案。
  • 样例输入
    5
    1 2 5 3 5
  • 样例输出
    2
  • 样例说明
    a[2] 和 a[4] 可能是三元组的中心。
  • 评测用例规模与约定
    对于 50% 的评测用例,2 <= n <= 100,0 <= 数列中的数 <= 1000。
    对于所有评测用例,2 <= n <= 1000,0 <= 数列中的数 <= 10000。

  • 答案
    #include<iostream>
    #include<string>
    #include<algorithm>
    using namespace std;
    int a[1005];
    int b[1005];
    int main()
    {
    	int n, ans = 0;//计数
    	int ind = 1;//用于存放符合条件的三元组中心的下标
    	cin >> n;
    	for (int i = 1; i <= n; i++) cin >> a[i];
    
    	for (int i = 1; i <= n - 2; i++)
    	{
    		for (int j = i + 1; j <= n - 1; j++)
    		{
    			for (int k = j + 1; k <= n; k++)
    			{
    				//如果满足题意,则将三元组中心的下标存入数组中
    				if (a[i] < a[j] && a[j] < a[k])
    				{
    					b[ind++] = j;
    				}
    			}
    		}
    	}
    	
    	//对存放入数组中的不同下标进行计数
    	sort(b, b + ind);
    	for (int i = 1; i < ind; i++)
    	{
    		if (b[i] != b[i - 1]) ans++;
    	}
    	cout << ans;
    	return 0;
    }
    

7. 音节判断

  • 问题描述
    小明对类似于 hello 这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。
    给定一个单词,请判断这个单词是否也是这种单词,如果是请输出yes,否则请输出no。
    元音字母包括 a, e, i, o, u,共五个,其他均为辅音字母。
  • 输入格式
    输入一行,包含一个单词,单词中只包含小写英文字母。
  • 输出格式
    输出答案,或者为yes,或者为no。
  • 样例输入
    lanqiao
  • 样例输出
    yes
  • 样例输入
    world
  • 样例输出
    no
  • 评测用例规模与约定
    对于所有评测用例,单词中的字母个数不超过100。

  • 答案
    #include<iostream>
    #include<string>
    using namespace std;
    int main()
    {
    	string s;
    	cin >> s;
    	bool part1 = false, part2 = false, part3 = false, part4 = false;
    	int i = 0;
    	for (i = 0; i < s.length(); i++)
    	{
    		//首字母
    		if (i == 0)
    		{
    			//如果为辅音,则part1为true
    			if (s[i] != 'a' && s[i] != 'e' && s[i] != 'i' && s[i] != 'o' && s[i] != 'u')
    			{
    				part1 = true;
    				continue;
    			}
    			//否则不满足题意,直接退出循环
    			else break;
    		}
    		//第一段辅音
    		if (part1 && !part2 && !part3 && !part4)
    		{
    			//如果目前为元音
    			if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
    			{
    				part2 = true;
    				continue;
    			}
    			//如果目前为辅音
    			else continue;
    		}
    		//第二段元音
    		if (part1 && part2 && !part3 && !part4)
    		{
    			//如果目前为元音
    			if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') continue;
    			//如果目前为辅音
    			else
    			{
    				part3 = true;
    				continue;
    			}
    		}
    		//第三段辅音
    		if (part1 && part2 && part3 && !part4)
    		{
    			//如果目前为元音
    			if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u')
    			{
    				part4 = true;
    				continue;
    			}
    			//如果目前为辅音
    			else continue;
    		}
    		//第四段元音
    		if (part1 && part2 && part3 && part4)
    		{
    			//如果目前为元音
    			if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') continue;
    			//如果目前为辅音
    			else
    			{
    				part4 = false;
    				break;
    			}
    		}
    	}
    	if (i == s.length() && part1 && part2 && part3 && part4) cout << "yes";
    	else cout << "no";
    	return 0;
    }
    

8. 长草

  • 问题描述
    小明有一块空地,他将这块空地划分为 n 行 m 列的小块,每行和每列的长度都为 1。
    小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。
    这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,这四小块空地都将变为有草的小块。
    请告诉小明,k 个月后空地上哪些地方有草。
  • 输入格式
    输入的第一行包含两个整数 n, m。
    接下来 n 行,每行包含 m 个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为 g,表示种了草。
    接下来包含一个整数 k。
  • 输出格式
    输出 n 行,每行包含 m 个字母,表示 k 个月后空地的状态。如果为小数点,表示为空地,如果字母为 g,表示长了草。
  • 样例输入
    4 5
    .g…

    …g…

    2
  • 样例输出
    gggg.
    gggg.
    ggggg
    .ggg.
  • 评测用例规模与约定
    对于 30% 的评测用例,2 <= n, m <= 20。
    对于 70% 的评测用例,2 <= n, m <= 100。
    对于所有评测用例,2 <= n, m <= 1000,1 <= k <= 1000。

  • 答案
    #include<iostream>
    #include<string>
    using namespace std;
    int map[1005][1005];//地图
    int dx[4] = { 0, -1, 0, 1 };//用于上下左右
    int dy[4] = { -1, 0, 1, 0 };//用于上下左右
    int main()
    {
    	int n, m, k;
    	
    	//输入数据
    	cin >> n >> m;
    	for (int i = 1; i <= n; i++)
    	{
    		string s;
    		cin >> s;
    		for (int j = 0; j < m; j++)
    		{
    			if (s[j] == '.') continue;
    			else map[i][j + 1] = 1;
    		}
    	}
    	cin >> k;
    	
    	//k个月的循环
    	for (int a = 1; a <= k; a++)
    	{
    		//遍历地图
    		for (int i = 1; i <= n; i++)
    		{
    			for (int j = 1; j <= m; j++)
    			{
    				//每次遍历第a个月中的草
    				if (map[i][j] == a)
    				{
    					//上下左右遍历
    					for (int t = 0; t < 4; t++)
    					{
    						int x0 = i + dx[t];
    						int y0 = j + dy[t];
    						//如果没有出局,则标记为第a+1个月的月数,以防在同一个月中遍历到新长出的草
    						if (x0 >= 1 && x0 <= n && y0 >= 1 && y0 <= m && map[x0][y0] == 0)
    						{
    							map[x0][y0] = a + 1;
    						}
    					}
    				}
    			}
    		}
    	}
    
    	//输出
    	for (int i = 1; i <= n; i++)
    	{
    		for (int j = 1; j <= m; j++)
    		{
    			if (map[i][j] != 0) cout << 'g';
    			else cout << '.';
    		}
    		cout << endl;
    	}
    	return 0;
    }
    

9. 序列计数

  • 问题描述
    小明想知道,满足以下条件的正整数序列的数量:

    1. 第一项为 n;
    2. 第二项不超过 n;
    3. 从第三项开始,每一项小于前两项的差的绝对值。

    请计算,对于给定的 n,有多少种满足条件的序列。

  • 输入格式
    输入一行包含一个整数 n。

  • 输出格式
    输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。

  • 样例输入
    4

  • 样例输出
    7

  • 样例说明
    以下是满足条件的序列:
    4 1
    4 1 1
    4 1 2
    4 2
    4 2 1
    4 3
    4 4

  • 评测用例规模与约定
    对于 20% 的评测用例,1 <= n <= 5;
    对于 50% 的评测用例,1 <= n <= 10;
    对于 80% 的评测用例,1 <= n <= 100;
    对于所有评测用例,1 <= n <= 1000。


  • 答案
    #include<iostream>
    using namespace std;
    int n;
    int ans;
    void dfs(int pre, int abs_v)
    {
    	if (abs_v == 0) return;//前两项的绝对值为0,返回
    
    	for (int i = 1; i < abs_v; i++)
    	{
    		ans++;
    		dfs(i, abs(pre - i));
    	}
    }
    int main()
    {
    	cin >> n;
    	
    	//第一项和第二项
    	for (int i = 1; i <= n; i++)
    	{
    		ans++;//两项的时候满足题意,ans++
    		dfs(i, abs(n - i));//从第三项开始深搜
    	}
    	cout << ans % 10000;
    	return 0;
    }
    

10. 晚会节目单

  • 问题描述
    小明要组织一台晚会,总共准备了 n 个节目。然后晚会的时间有限,他只能最终选择其中的 m 个节目。
    这 n 个节目是按照小明设想的顺序给定的,顺序不能改变。
    小明发现,观众对于晚上的喜欢程度与前几个节目的好看程度有非常大的关系,他希望选出的第一个节目尽可能好看,在此前提下希望第二个节目尽可能好看,依次类推。
    小明给每个节目定义了一个好看值,请你帮助小明选择出 m 个节目,满足他的要求。
  • 输入格式
    输入的第一行包含两个整数 n, m ,表示节目的数量和要选择的数量。
    第二行包含 n 个整数,依次为每个节目的好看值。
  • 输出格式
    输出一行包含 m 个整数,为选出的节目的好看值。
  • 样例输入
    5 3
    3 1 2 5 4
  • 样例输出
    3 5 4
  • 样例说明
    选择了第1, 4, 5个节目。
  • 评测用例规模与约定
    对于 30% 的评测用例,1 <= n <= 20;
    对于 60% 的评测用例,1 <= n <= 100;
    对于所有评测用例,1 <= n <= 100000,0 <= 节目的好看值 <= 100000。

  • 答案
    #include<iostream>
    #include<cstring>
    #include<stack>
    #include<ctime>
    #define ll long long
    
    using namespace std;
    
    const int N = 100000 + 10;
    
    int lg[N] = { -1 };
    int tree[N * 4];
    int Data[N];
    
    int _pow(int a)
    {
    	return 1 << a;
    }
    
    void build_tree(int node, int l, int r)
    {
    	if (l == r)
    	{
    		tree[node] = l;
    		return;
    	}
    	int mid = (l + r) / 2;
    	int left = node * 2;
    	int right = left + 1;
    	build_tree(left, l, mid);
    	build_tree(right, mid + 1, r);
    	int a = tree[left];
    	int b = tree[right];
    	tree[node] = Data[a] > Data[b] ? a : b;
    }
    
    
    int query(int l, int r, int ql, int qr, int node)
    {
    	if (ql <= l && qr >= r) return tree[node];
    	int mid = (l + r) / 2;
    	int ans = -1;
    	if (ql <= mid) ans = query(l, mid, ql, qr, node * 2);
    	if (qr > mid)
    	{
    		if (ans == -1) ans = query(mid + 1, r, ql, qr, node * 2 + 1);
    		else
    		{
    			int k = query(mid + 1, r, ql, qr, node * 2 + 1);
    			ans = Data[ans] > Data[k] ? ans : k;
    		}
    	}
    	return ans;
    }
    
    int main()
    {
    	int n, m;
    	cin >> n >> m;
    	for (int i = 1; i <= n; i++)
    	{
    		cin>>Data[i];
    		lg[i] = lg[i / 2] + 1;
    	}
    	build_tree(1, 1, n);
    	int pos1 = 1, pos2 = n - m + 1, pos_max = 1;
    	while (pos1 < pos2 && pos2 <= n)
    	{
    		pos_max = query(1, n, pos1, pos2, 1);
    		printf("%d ", Data[pos_max]);
    		pos1 = pos_max + 1;
    		pos2++;
    	}
    	while (pos2 != n + 1)
    	{
    		printf("%d ", Data[pos2++]);
    	}
    	return 0;
    }
    
    引用:https://blog.csdn.net/weixin_44267044/article/details/105133352
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值