【No.1】蓝桥杯手算与思维题|门牌制作|迷宫|星期一|乘积尾零|付账问题(C++)

技巧:手算

  • 应用场合:填空题
  • 手算的目的:减少做题时间,省下时间做编程题。
    手段:
  • 不编码,或者只做部分编码
  • 用推理获得答案
  • 用软件工具帮助计算
    方法:
  • 巧用编辑器
  • 心算手数
  • 巧用 Excel
  • 巧用 Python
例题
1.门牌制作

0门牌制作 - 蓝桥云课 (lanqiao.cn)
问题描述:
从 1 到 2020 的所有数字中,共有多少个 2?

  • 先编码连续打印出 1∼2020 这 2020 个数字
  • 然后粘贴到任何一个编辑器中
  • 选查询或替换功能,查找或替换字符 “2”,共 624 次,就是答案。
    简单直接,不用思考
    ![[Pasted image 20240228182849.png]]
    ![[Pasted image 20240228182918.png]]
    在这里插入图片描述

![[Pasted image 20240228183213.png]]
除去for循环条件里的两个2,总共有624个2

2. 迷宫

0迷宫 - 蓝桥云课 (lanqiao.cn)
问题描述:
给出一个迷宫,问迷宫内的人有多少能走出来。迷宫如图所示:每个位置上有一个人,共 100 人。每个位置有指示牌,L 表示向左走,R 表示向右走,U 表示向上走,D 表示向下走。

U D D L U U L R U L 
U U R L L L R R R U 
R R U U R L D L R D 
R U D D D D U U U U 
U R U D L L R R U U  
D U R L R L D L R L 
U L L U R L L R D U 
R D L U L L R D D D 
U U D D U D U D L L 
U L R D L U U R R R
  • 正解:DFS 搜索,编码 10 分钟。
  • 技巧:直接用手画图标记 3-5 分钟。

![[Pasted image 20240228210548.png]]

共31个

3. 星期一

1.星期一 - 蓝桥云课 (lanqiao.cn)
问题描述:
整个 20 世纪(1901年1月1日至 2000年12月31日之间),一共有多少个星期一?
思路:
用Excel,在一个格子里输入日期1901年1月1日,另一个格子输入2000年12月31日,然后两个格子相减得36524 天,除以77得5217.7周。
![[Pasted image 20240228211915.png]]

再看1901年11月11日是星期几。
用Excel点1901年1月1日这一格的“设置单元格式-数字-日期-星期三”,点击“确定”,得“星期二”,即1901年1月1日是星期二,36524是5217周多几天,最后几天没有星期一,说明答案就是5217。
![[Pasted image 20240228211940.png]]

![[Pasted image 20240228212024.png]]

也可以直接利用 Excel“单元格格式”对话框得出2000年12月31日刚好是星期天,从星期二至星期天之间没有星期一。

巧用 Python

填空题遇到字符、大数字、日期问题,Python 是首选。
•即使参加 C/C++、Java 组比赛,也要学一些 Python,以方便手算,或用来做对比测试。
•这几种语言的编译器,在比赛机器上都有。
•写 Python 代码既简单又快,代码长度一般比 C/C++、Java 短很多。例如 30 行的 C++代码,用 Python 写只需要 20 行。

4. 星期一

1.星期一 - 蓝桥云课 (lanqiao.cn)
问题描述:
整个 20 世纪(1901 年 1 月 1 日至 2000 年 12 月 31 日之间),一共有多少个星期一?
直接用 Python datetime 库求解,第 4 行可以输出某个日期是星期几。

from datetime import* 

# 定义两个日期对象,dt1表示1901年1月1日,dt2表示2000年12月31日
dt1=datetime(1901,1,1) 
dt2=datetime(2000,12,31) 

# 输出dt1对应的星期几(周一为0,周二为1,以此类推)
print(dt1.weekday()) 
# 周一为0,周二为1... 

# 计算两个日期之间的天数差,并以整数除以7,得到两个日期之间相差的周数
td=dt2-dt1 

print(td.days//7)

相对应的使用 C++同样可以完成,但是编码复杂:

#include <iostream> 
using namespace std; 
int res; //用于存储总天数的变量

//判断是否为闰年的函数
bool is_r(int n){ 
	if((n % 4 == 0 && n % 100 != 0) || n % 400 == 0) 
		return true; 
	return false; 
} 
int main(){ 
	//循环遍历从1901年到2000年的每一年
	for(int i = 1901;i <= 2000;i ++) 
		// 如果是闰年,增加366天,否则增加365天
		if(is_r(i)) 
			res += 366; 
		else 
			res += 365; 
	//将总天数除以7,得到整数部分,表示从1901年到2000年之间的完整周数
	int x = res / 7; 
	//输出结果
	cout << x << endl; 
	return 0; 
}
5. 乘积尾零

0乘积尾零 - 蓝桥云课 (lanqiao.cn)
【问题描述】
给出100个整数(这里省略题目给的100个数),问它们乘积的末尾有多少个零。
最简单题解:

  • 直接连乘:几千位的大数
  • 然后统计末尾的00
    ![[Pasted image 20240228223117.png]]

但是 C++ 装不下这么大的数字,所以要进行处理:

#include <bits/stdc++.h> 
using namespace std; 
int main()
{ 
	int cnt2=0,cnt5=0; // 用于统计2和5的因子个数

	// 嵌套循环,处理一个10x10的矩阵
	for (int i=1;i<=10;i++) 
	{ 
		for (int j=1;j<=10;j++) 
		{ 
			int x; 
			cin>>x; // 从输入中读取一个整数
			// 处理2的因子,统计其个数
			while (x%2==0) 
				cnt2++,x/=2; 
			// 处理5的因子,统计其个数
			while (x%5==0) 
				cnt5++,x/=5; 
		} 
	} 
	// 输出2和5的因子个数中的较小值
	cout<<min(cnt2,cnt5)<<'\n'; 
	return 0; 
}

思维题

  • 不需要涉及某种算法的题目。
  • 只要学过编程语言,就能够解答。
  • 主要考核学生的思维、逻辑和编码能力,强调脑筋急转弯的解决方式。
  • 这类题目包括模拟题、构造题、思维题以及找规律题,统称为“思维题(杂题)”。
  • 每年蓝桥杯都会设置这类题目,而且可能有多道,是考试中的重要得分点。
  • 杂题涵盖了各种难度,有些可能相对简单,而另一些可能相对较难。
6. 付账问题

0付账问题 - 蓝桥云课 (lanqiao.cn)
【题目描述】
现在有n个人出去吃饭,他们总共消费了S元。其中第i个人带了ai​元。幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?
为了公平起见,我们希望在总付钱量恰好为S的前提下,最后每个人付的钱的标准差最小。这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是1分钱的整数倍。你需要输出最小的标准差是多少。
标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的"偏差有多大"。
解决思路:
如果每个人携带的钱足够多,每个人平均支付相同的金额,
然而,总会有人的钱不够,这时我们考虑两种情况:
(1)第i个人携带的钱不足以达到平均数avg,那么他只能支付他所携带的全部钱ai​。
(2)第i个人携带的钱超过平均数avg,那么他可以支付多一些。
解决步骤:
(1)对ai​ 进行从小到大的排序;
(2)前一部分人的钱不足以支付平均数,因此他们每个人支付所有携带的钱;
(3)从总支付数中减去前一部分人支付的钱,得到剩余金额′S′,以及后一部分人的平均支付数avg′。
(4)后一部分人携带的钱较多,他们可以支付多一些。这部分人又可以分为两类:

  • (i)相对富裕但仍然不足以支付avg′ 的人,他们需要支付所有携带的钱;
  • (ii)非常富裕的人,无论如何摊分,他们都有余额。
    由于前面一部分人不足以支付avg,因此后面足够支付avg′的人不能只支付avg。相反,他们应该尽可能地每个人支付相同的金额。
    因为有人支付不足,总有人支付过多,由于是标准差(方差的平方根),因此每个人支付的金额差距越小越好。
#include <bits/stdc++.h> 
using namespace std; 
const int M = 5e5; 
long long a[M]; 
int main(){     
	int n;  
	long long s;     
	scanf("%d %lld",&n,&s);     
	for(int i=1;i<=n;i++)  
		scanf("%lld",&a[i]);     
	sort(a+1,a+n+1);       
	// 对数组a进行从小到大的排序     
	double avg = 1.0*s/n;  
	// 计算平均值     
	double sum = 0.0;     
	for(int i=1;i<=n;i++){         
		if(a[i]*(n+1-i) < s){ 
			//需要把钱全拿出的人: 
			//(1)钱不够平均数的,(2)钱够平均数,但也不是很多的             sum += (a[i]-avg)*(a[i]-avg);             
			s -= a[i];            
			//更新剩余钱数         
		}         
		else{       
			//不用把钱全拿出的人:非常有钱,不管怎么平均都够        
			double cur_avg = 1.0*s/(n+1-i);     
			//更新平均出钱数             
			sum += (cur_avg-avg)*(cur_avg-avg)*(n+1-i);          
			break;         
		}     
	}     
	printf("%.4lf",sqrt(sum/n));   
	// 输出平均值的标准差,保留四位小数  
	return 0; 
}
  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值