蓝桥杯题目——带分数
文章目录
- 前言
- 解题思路
- 全排列方法
- 递归实现
- 循环实现
- 组合数方法
- 循环实现
- 递归实现
- 浮点转整型思想
前言
本文介绍蓝桥杯题目——带分数,并且对其中包含的方法与思想进行总结,本文是上半部分。
参考题目:带分数
解题思路
本题虽麻烦,但有一个思想上很简单的做法(代码上很复杂),设N=a+b/c。
第一步先将1~9全排列,把每一种情况中的9个数分成三份,分别令其为a,b,c。
这样,你就获得了一组满足条件的abc,然后让a+b/c与N判断一下是否相等,每出现一个相等的情况,就让计数变量+1,打印计数变量,就能得出最后的答案。
但是,因此也引出了第一个问题,怎样把1~9全排列? 亦或是更具一般性的说法,怎样把1~n全排列?
全排列方法
递归实现
递归实现的思想很简单,拿本题举例,一共有九个位置,每个位置放一个数,第一个位置有9种情况,第二个位置有8种情况,第三个位置有7种情况…
因为每个数只能使用一次,所有你在某个位置存在一个数据时,要先判断这个数有没有被用过。
创建arr数组保存每一种情况,创建used数组,利用哈希表的思想记录每个数是否被用过,创建step变量记录当前正在操作第几个位置,输入一个n代表要全排列1~n。
注意: 这四个变量或数组的作用域须为全局,或用static修饰。
int arr[10];
int used[10];
int step = 0;
int n = 0;int main()
{scanf("%d", &n);A(n);return 0;
}
随后,我们在函数A内部对每个位置都进行1~n的枚举,枚举好一个数了,就在used数组中记录这个数已经被用过了,同时让step+1,代表我们该枚举下一个位置了。
注意: 枚举的时候不要忘记判断这个数是否被用过,且递归返回之时不要忘记恢复现场。
void A(int n)
{int i = 0;for (i = 0; i < n; i++){if (used[i + 1] == 0){used[i + 1] = 1;arr[step] = i + 1;step++;A(n);step--;used[i + 1] = 0;}}
}
最后,当step与n相等,即所有的位置都选完数了,打印arr数组即可。(设step=8,则arr[step]为第九个数,因此本题中step为9时满足打印条件)
void A(int n)
{if (step == n){int i = 0;for (i = 0; i < n; i++){printf("%d ", arr[i]);}printf("\n");return;}int i = 0;for (i = 0; i < n; i++){if (used[i + 1] == 0){used[i + 1] = 1;arr[step] = i + 1;step++;A(n);step--;used[i + 1] = 0;}}
}
如此,便完成了1~n的全排列,如果你想对这些排列数进行使用,直接把打印函数换成需要的函数进行操作即可。
循环实现
至于用循环实现1~n全排列,其本质就是一遍遍地遍历,n较小时使用比较合适,推荐在3以下使用,再大的话代码就会很冗杂。
伪代码如下:
int main()
{for (int i = 0; i < 9; i++)for (int j = 0; j < 9; j++)for (int k = 0; k < 9; k++)......return 0;}
组合数方法
上文说到的解题方法中,当我们排列出了一种情况后,接着要把这种情况的9个数分成三部分,分别令其为a、b、c,那么,就引出了下一个问题,怎样分割这九个数呢? 亦或更具一般性的说法,怎样将数组中的n个数分割成不同的部分?
中学数学中有个章节叫排列组合,其中有一种解题方法叫做隔板法,即把n个数排成一排,往它们之间放隔板,每放一个隔板就能把一排数分成两部分,每加一个隔板,就多一个部分,像这样:
这里,我有九个球。
九个球之间共有八个空,如果要放3个隔板,我们只需要在8个空之间选择3个即可,也就是组合数C83。
如图,放了三个板子,把原来一排的球,分成了四个部分。
因此,若想把1~9分成三部分,只需要在其间的空内,放入两个隔板即可,也就是组合数C82。
循环实现
相比排列,组合因其的性质,在大多数情况下更适合用循环完成。
C97=C92,C86=C82…
与排列相比,组合数多数情况可以凑出一个较小的m,因此,即使用循环写,代码也不会太复杂。
当然,如果m无论怎样凑也到不了3以下,该用递归还得用递归。
以本题举例,在8个数中选取2个数,用循环遍历即可:
注意: 利用循环完成组合数的前提是已经知道n和m分别是多少,如果n和m还等着用户去输入,那么循环实现就不可取了。
int main()
{int i = 0;for (i = 1;i<=7; i++){int j = 0;for (j = i + 1; j <= 8; j++){printf("%d %d\n", i, j);}}return 0;
}
递归实现
首先创建arr存储枚举的信息,创建step记录当前正在枚举第几位,创建fir当前位置从第几个数开始枚举,创建n表示总数,创建m表示需要组合的个数,创建num表示当前还需要选取几位。
int arr[10];
int step = 0;
int fir =0;
int n = 0;
int m = 0;
int num = 0;int main()
{scanf("%d %d", &n, &m);num = m;C(n, m);return 0;
}
随后从fir开始对arr[step]开始枚举,枚举好一位后step要+1,表示要开始枚举下一位了。
fir赋为当前位被枚举值,以便于下一位的枚举时不包含上一位的数。例如此时的arr[step]被赋为1,则就让fir等于1,那么下一位的枚举时,就会从arr[1]开始,即第二个数。
每枚举成功一个位置,就要让num–,当num等于0时,代表已经枚举完毕,可以打印了。
下面代码中有一部分代表剪枝,其中n-fir表示还有几个数可以选择,num表示还需要选几个数,如果满足前者小于后者,则无解,可以先返回。
例如:如果你第一个位置枚举一个8,那么你在下一个位置时将从9开始枚举,但是n也是9,因此只有一个数可以用了,但是num还是3,所以这种情况无解。
void C(int n, int m)
{if (n-fir<num)//剪枝,加快速度{return;}if (num==0){int i = 0;for (i = 0; i < m ;i++){printf("%d", arr[i]);}printf("\n");}int i = 0;for (i = fir; i < n; i++){arr[step] = i + 1;step++;fir = i + 1;num--;C(n, m);num++;step--;}
}
如此,便知道如何实现从八个空中选两个空,插入隔板了。
利用组合数找出两个下标,利用这两个下标进行分割即可。
浮点转整型思想
众所周知,计算机中的浮点型是用SME方法存储,其精度是有限的,不能准确的表示一个小数,因此判断时会有误差。
所以,遇到式子包含浮点型数据时,可以优先考虑能否把一个浮点型式子,转换成都是由整型构成的式子,这样就可以准确无误了,例如本题:
可以转化为:
这样就完全是整型的式子,也不用考虑精度丢失的问题。
感谢您的阅读与耐心~
蓝桥杯题目——带分数相关推荐
- 蓝桥杯题目:九宫幻方(C++实现)(DFC)(打卡1)
题目: 问题描述 小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行.每一列和每一条对角线的和都是相同的. 三阶 ...
- 蓝桥杯题目练习 提升篇 [蓝桥杯2019初赛]迷宫
[蓝桥杯2019初赛]迷宫 题目描述 下图给出了一个迷宫的平面图,其中标记为1 的为障碍,标记为0 的为可 以通行的地方. 010000 000100 001001 110000 迷宫的入口为左上角, ...
- PREV-3_蓝桥杯_带分数
问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. 注意特征:带分数中,数字1~9分别出现且只出现一次( ...
- 蓝桥杯-题目:猜算式
题目:猜算式 你一定还记得小学学习过的乘法计算过程,比如: 273 x 15 ------ 1365 273 ------ 4095 请你观察如下的乘法算式 *** x *** -------- ** ...
- 2013年蓝桥杯题目与解答
1. 题目标题: 高斯日记 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示那一天 ...
- 蓝桥杯题目练习(旅行家的预算)
算法训练VIP 旅行家的预算 原题链接:旅行家的预算 题目描述 一个旅行家想驾驶汽车以最少的费用从一个城市 到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车油箱的容量C(以升为单 ...
- 蓝桥杯题目练习(JAM计数法)
算法训练VIP JAM计数法 题目描述 Jam是个喜欢标新立异的科学怪人.他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩.在他的计数法中,每个数字的位数都是相同的 ...
- 蓝桥杯题目 2682: 蓝桥杯2022年第十三届省赛真题-GCD
题目描述 给定两个不同的正整数 a, b,求一个正整数 k 使得 gcd(a + k, b + k) 尽可能大,其中 gcd(a, b) 表示 a 和 b 的最大公约数,如果存在多个 k,请输出所有满 ...
- 蓝桥杯题目讲解(下)
1.定义二维数组int a[5][6],则该二维数组可存储()个数组元素. A.20 B.25 C.30 D.16 这道题考察二维数组的知识,5 * 6 = 30,所以答案是C,(以前我有写过关于二维 ...
最新文章
- java怎么做简易的游戏,Java小项目之《简易桌面小游戏》
- 实战SSM_O2O商铺_36【商品】商品列表之Dao+Service+Controller层的实现
- HBase学习笔记2 - HBase shell常用命令
- 训练及优化神经网络基本流程之第0到6步
- Linux搭建smb共享ftp服务器——windows无法写入samba共享路径 无操作权限的问题解决
- 软件开发报价模板_模板类app开发价格是多少钱?
- html5 2d绘图,HTML5 canvas绘图
- UnityShader7:内置包含文件UnityCG.cginc与GG/HLSL语义
- 统计学习方法——统计学习基础(一)
- 微信公众号开发基本流程
- python与plc进行串口通信,寄存器写数据 欧姆龙plc
- 修改系统时区 /etc/localtime
- android 通知图标大小,android – 通知栏显示大图标和小图标
- 值得收藏|基于全球切片解析标准TMS的瓦片规则
- 如何消除原生Android,如何消除原生Android网络状态上的惊叹号
- 大学生用什么软件学c语言,当代大学生必须的几款APP
- NLP之文本分类:「Tf-Idf、Word2Vec和BERT」三种模型比较
- 6.Spring security中的rememberMe
- navicat 导出excel数据不全问题
- 想把cocos2d-x的框架研究研究,权且开个头吧,从demo开始,给自己加油!!!!