文章目录

  • 前言
  • 解题思路
  • 全排列方法
    • 递归实现
    • 循环实现
  • 组合数方法
    • 循环实现
    • 递归实现
  • 浮点转整型思想

前言

本文介绍蓝桥杯题目——带分数,并且对其中包含的方法与思想进行总结,本文是上半部分。


参考题目:带分数

解题思路

本题虽麻烦,但有一个思想上很简单的做法(代码上很复杂),设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方法存储,其精度是有限的,不能准确的表示一个小数,因此判断时会有误差。

所以,遇到式子包含浮点型数据时,可以优先考虑能否把一个浮点型式子,转换成都是由整型构成的式子,这样就可以准确无误了,例如本题:


可以转化为:

这样就完全是整型的式子,也不用考虑精度丢失的问题。


感谢您的阅读与耐心~

蓝桥杯题目——带分数相关推荐

  1. 蓝桥杯题目:九宫幻方(C++实现)(DFC)(打卡1)

    题目: 问题描述 小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将1~9不重复的填入一个3*3的矩阵当中,使得每一行.每一列和每一条对角线的和都是相同的. 三阶 ...

  2. 蓝桥杯题目练习 提升篇 [蓝桥杯2019初赛]迷宫

    [蓝桥杯2019初赛]迷宫 题目描述 下图给出了一个迷宫的平面图,其中标记为1 的为障碍,标记为0 的为可 以通行的地方. 010000 000100 001001 110000 迷宫的入口为左上角, ...

  3. PREV-3_蓝桥杯_带分数

    问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. 注意特征:带分数中,数字1~9分别出现且只出现一次( ...

  4. 蓝桥杯-题目:猜算式

    题目:猜算式 你一定还记得小学学习过的乘法计算过程,比如: 273 x 15 ------ 1365 273 ------ 4095 请你观察如下的乘法算式 *** x *** -------- ** ...

  5. 2013年蓝桥杯题目与解答

    1. 题目标题: 高斯日记 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们知道,那个整数就是日期,它表示那一天 ...

  6. 蓝桥杯题目练习(旅行家的预算)

    算法训练VIP 旅行家的预算 原题链接:旅行家的预算 题目描述 一个旅行家想驾驶汽车以最少的费用从一个城市 到另一个城市(假设出发时油箱是空的).给定两个城市之间的距离D1.汽车油箱的容量C(以升为单 ...

  7. 蓝桥杯题目练习(JAM计数法)

    算法训练VIP JAM计数法 题目描述 Jam是个喜欢标新立异的科学怪人.他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩.在他的计数法中,每个数字的位数都是相同的 ...

  8. 蓝桥杯题目 2682: 蓝桥杯2022年第十三届省赛真题-GCD

    题目描述 给定两个不同的正整数 a, b,求一个正整数 k 使得 gcd(a + k, b + k) 尽可能大,其中 gcd(a, b) 表示 a 和 b 的最大公约数,如果存在多个 k,请输出所有满 ...

  9. 蓝桥杯题目讲解(下)

    1.定义二维数组int a[5][6],则该二维数组可存储()个数组元素. A.20 B.25 C.30 D.16 这道题考察二维数组的知识,5 * 6 = 30,所以答案是C,(以前我有写过关于二维 ...

最新文章

  1. java怎么做简易的游戏,Java小项目之《简易桌面小游戏》
  2. 实战SSM_O2O商铺_36【商品】商品列表之Dao+Service+Controller层的实现
  3. HBase学习笔记2 - HBase shell常用命令
  4. 训练及优化神经网络基本流程之第0到6步
  5. Linux搭建smb共享ftp服务器——windows无法写入samba共享路径 无操作权限的问题解决
  6. 软件开发报价模板_模板类app开发价格是多少钱?
  7. html5 2d绘图,HTML5 canvas绘图
  8. UnityShader7:内置包含文件UnityCG.cginc与GG/HLSL语义
  9. 统计学习方法——统计学习基础(一)
  10. 微信公众号开发基本流程
  11. python与plc进行串口通信,寄存器写数据 欧姆龙plc
  12. 修改系统时区 /etc/localtime
  13. android 通知图标大小,android – 通知栏显示大图标和小图标
  14. 值得收藏|基于全球切片解析标准TMS的瓦片规则
  15. 如何消除原生Android,如何消除原生Android网络状态上的惊叹号
  16. 大学生用什么软件学c语言,当代大学生必须的几款APP
  17. NLP之文本分类:「Tf-Idf、Word2Vec和BERT」三种模型比较
  18. 6.Spring security中的rememberMe
  19. navicat 导出excel数据不全问题
  20. 想把cocos2d-x的框架研究研究,权且开个头吧,从demo开始,给自己加油!!!!

热门文章

  1. 大航海家 ——OO思想的类间关系(转)
  2. spring官方文档中文
  3. MFC使用Create函数创建对话框失败,new出来的对话框内存泄漏
  4. 论文的技术路线流程图如何绘制?
  5. php 密码正则表达式,验证用户设置的密码强度正则表达式
  6. 【WY】数据分析 — Matplotlib 阶段一 :基础语法 三 —— 创建子图
  7. 矩阵转置 Python
  8. uniapp 屏幕手势
  9. springboot的yml文件没有绿叶
  10. Tomcat的8005、8080、8009、8443端口号