第十二届蓝桥杯真题做题笔记

2、卡片

笔记:

直接巧用排列组合求解即可:

我们通过对样例说明进行分析可知:想要分给n个小孩,那么我们就需要满足C(K, 2) + K >= n才能满足。

#include<bits/stdc++.h>
using namespace std;

int com(int up, int down){
	if(up > down)	return 0;
	if(up == down)	return 0;
	int res = 1;
	for(int i = 1; i <= up; i++){
		res = res * (down - i + 1) / i;
	}
	return res;
}

int main(){
	int n;
	cin >> n;
	int down = 2;
	while(com(2, down) + down < n){
		down++;
	} 
	cout << down << endl;
	return 0;
}

4、货物摆放:

题目:

小蓝有一个超大的仓库,可以摆放很多货物。

现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。

小蓝希望所有的货物最终摆成一个大的长方体。即在长、宽、高的方向上分别堆 L、W、H 的货物,满足 n = L×W×H。

给定 n,请问有多少种堆放货物的方案满足要求。

例如,当 n = 4 时,有以下 6种方案:1×1×4、1×2×2、1×4×1、2×1×2、2 × 2 × 1、4 × 1 × 1

请问,当 n = 2021041820210418(注意有 16 位数字)时,总共有多少种方案?
 

笔记:

这道题三重暴力循环会超时,因为n太大了,所以我们需要将预处理数据的大小压缩一下,因为n = l * h * w,所以我们可以只求l,h,w的组合,为了不在从0开始一个一个得去找找三个符合的数,我们可以直接去获取n的所有因子的数列,再从这个数列中去找到符合的l,h,w的值。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; 
vector<ll> res(1e7, 0);
ll n = 2021041820210418;
int main(){
	ll index = 0;
	for(ll i = 1; i <= sqrt(n); i++){
		if(n % i == 0){
			res[index++] = i;
			if(i * i != n){
				res[index++] = n / i;
			}
		}
	}
	res.resize(index + 1);
	ll count = 0;
	for(ll l = 0; l < res.size(); l++){
		for(ll h = 0; h < res.size(); h++){
			for(ll w = 0; w < res.size(); w++){
				if(res[l] * res[h] * res[w] == n){
					count++;
				}
			}
		}
	}
	cout << count;
	
	
	return 0;
}

3、直线

题目:

在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上, 那么这些点中任意两点确定的直线是同一条。

给定平面上 2 × 3 个整点(�,�)∣0≤�<2,0≤�<3,�∈�,�∈�(x,y)∣0≤x<2,0≤y<3,x∈Z,y∈Z​,即横坐标 是 00 到 11 (包含 0 和 1) 之间的整数、纵坐标是 0 到 2 (包含 0 和 2) 之间的整数 的点。这些点一共确定了 11 条不同的直线。

给定平面上 20×2120×21 个整点 (�,�)∣0≤�<20,0≤�<21,�∈�,�∈�(x,y)∣0≤x<20,0≤y<21,x∈Z,y∈Z,即横 坐标是 00 到 1919 (包含 00 和 1919) 之间的整数、纵坐标是 00 到 2020 (包含 00 和 2020​) 之 间的整数的点。

请问这些点一共确定了多少条不同的直线。

笔记:

这道题我们就遵循一个原则:两点确定一条直线,我们只需要找到斜率是独一无二的直线即可,有公式y = k*x + b我们可以获取两点连成直线的斜率以及b,接着就暴力搜索出符合的(k, b),这里我们需要注意的是要对这些组合进行去重,我们可以使用set容器来去重,最后我们还需要注意:还存在斜率不存在的直线也就是平行于x轴的直线,最后就是将set容器的大小再加上这些平行于x轴的直线的数组即可。

#include<bits/stdc++.h>
using namespace std;

set<pair<double, double> > st;
int main(){
	for(int x1 = 0; x1 < 21; x1++){
		for(int y1 = 0; y1 < 20; y1++){
			for(int x2 = x1 + 1; x2 < 21; x2++){
				for(int y2 = 0; y2 < 20; y2++){
					double k = (double)(y1 - y2) / (x1 - x2);
					double b = (double)(x1 * y2 - x2 * y1) / (x1 - x2);
					st.insert(make_pair(k, b));
				}
			}
		}
	}
	cout << st.size() + 21;
	return 0;
}

7、砝码称重:

题目:

你有一架天平和 �N 个砝码,这 �N 个砝码重量依次是 �1,�2,⋅⋅⋅,��W1​,W2​,⋅⋅⋅,WN​。

请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。

输入格式

输入的第一行包含一个整数 �N。

第二行包含 �N 个整数:�1,�2,�3,⋅⋅⋅,��W1​,W2​,W3​,⋅⋅⋅,WN​。

输出格式

输出一个整数代表答案。

样例输入

3
1 4 6

样例输出

10

样例说明

能称出的 1010 种重量是:1、2、3、4、5、6、7、9、10、111、2、3、4、5、6、7、9、10、11​。

1=1;1=1;

2=6−4(2=6−4(天平一边放 66,另一边放 4);4);​

3=4−1;3=4−1;

4=4;4=4;

5=6−1;5=6−1;​

6=6;6=6;

7=1+6;7=1+6;

9=4+6−1;9=4+6−1;

10=4+6;10=4+6;

11=1+4+6。11=1+4+6。

笔记:

这道题可以采用bfs的思想与背包思想相结合:

我们在这里将dp数组设为:前i个元素能否凑成j的bool值,将dp[0][0]初始化为0,接着然后我们遍历dp数组,如果dp[i - 1][j] = true呢么i个元素也一定可以凑成j,所以dp[i][j] = true,然后开始扩散:dp[i][j + nums[i]] = true,dp[i][j - nums[i]] = true,dp[i][nums[i] - j] = true;

扩散完一遍,我们就可以对数组进行检查,如果dp[i][j] = true那么就count ++。

有几点需要注意的是:

(1)这里我们在输入nums数组的时候不可以从0开始加入元素,因为为了符合后续dp数组的遍历:i表示前i个元素,所以我们的nums数组要从1开始。

(2)在dp数组中进行遍历搜索的时候我们无需提前判断当前dp[i][j]是否为false,因为我们是符合了bfs一层一层向外扩散,所以我们不单单是对fasle的dp元素进行判断处理,对true的dp元素也一样要判断处理。

#include<bits/stdc++.h>
using namespace std;

int main(){
	int n;
	cin >> n;
	vector<int> nums(n + 1, 0);
	int sum = 0;
	int count = 0;
	for(int i = 1; i <= n; i++){
		cin >> nums[i];
		sum += nums[i];
	}
	vector<vector<bool> > dp(n + 1, vector<bool>(sum + 1, false));
	dp[0][0] = true;// 前i中元素是否能够凑成j 
	for(int i = 1; i <= n; i++){
		for(int j = 0; j <= sum; j++){
			if(dp[i][j] == false){
				if(dp[i - 1][j] == true){
					dp[i][j] = true;
					dp[i][j + nums[i]] = true; // 会略过nums[0]的情况。 
					if(j > nums[i]){
						dp[i][j - nums[i]] = true;
					}else{
						dp[i][nums[i] - j] = true;
					}
				}
			}
		}
	}
	for(int j = 1; j <= sum; j++){
		if(dp[n][j])	count++;
	}
	cout << count;
	
	return 0;
}

10、括号序列:

题目:

笔记:

(1)首先明确dp数组含义:

dp[ i ][ j ]:表示第i个右括号前添加j个左括号的组合数。

(2)状态转移方程:

dp[ i ][ j ] = dp[ i - 1 ][ 0 ] + ......... + dp[ i - 1 ][ j ]:

也就是i-1号有括号前加0个左括号,i - 1号右括号到i好有括号之间加j个左括号 到i - 1号有括号前加j个左括号, i- 1号右括号到i号右括号之间加0个左括号。

通过对上面状态转移方程的进一步分析我们就可以发现并不能从0开始遍历,我们的i的遍历范围是从第一个到第n个,那我们j的遍历范围就应该是从(i  - suml(前面剩余的左括号的数量) -----  j)也就是目的是让前面的合法。

(3)初始化:

按照我们定义的含义来分析:首先看第一个右括号前面我们如没有剩余的左括号,那么添加1 - j的左括号的方案数都为1,若果有剩余左括号那么前面添加0个左括号的方案数为1。

  • 39
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是第十四届蓝桥杯Python组真题的部分内容: 一、选择题(每题5分,共40分) 1. 下列哪个不是Python的内置数据类型? A. int B. float C. char D. str 答案:C 2. 下列哪个不是Python的保留字? A. and B. or C. not D. xor 答案:D 3. 下列哪个不是Python的标准模块? A. os B. sys C. math D. timeit 答案:D 4. 下列哪个Python库可以用于科学计算? A. NumPy B. SciPy C. Matplotlib D. All of the above 答案:D 5. 下列哪个Python库可以用于机器学习? A. TensorFlow B. Keras C. PyTorch D. All of the above 答案:D 6. 下列哪个Python库可以用于爬虫? A. Requests B. BeautifulSoup C. Scrapy D. All of the above 答案:D 7. 下列哪个Python库可以用于图像处理? . OpenCV B. Pillow C. Scikit-image D. All of the above 答案:D 8. 下列哪个Python库可以用于游戏开发? A. Pygame B. Panda3D C. PyOpenGL . All of the above 答案:D 二、编程题(每题20分,共60分) 1. 编写一个Python程序,输入一个字符串,将其中的大写字母转换为小写字母,将其中的小写字母转换为大写字母,然后输出转换后的字符串。 2. 编写一个Python程序,输入一个整数n,输出n的阶乘。 3. 编写一个Python程序,输入一个字符串,判断该字符串是否为回文字符串。如果是回文字符串,则输出True,否则输出False。 以上是部分内容,完整的第十四届蓝桥杯Python组真题可以在蓝桥杯官网上找到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值