(大一萌新都能听懂的)蓝桥杯 第十五届(2024)1.2.3.4.6.7真题思路复盘 ...

打印 上一主题 下一主题

主题 1583|帖子 1583|积分 4749

目录
T1 握手题目(标题难度1 知识难度1)
题目形貌
知识点:握手
T2 小球反弹(标题难度7 知识难度3)
题目形貌
审题
思路:模拟
调整思路:解三角形
T3 好数(标题难度4 知识难度3)
题目形貌
审题
思路:数学递推
调整思路:动态规划
T4 R格式(标题难度5 知识难度3)
题目形貌
审题
思路:高精度
T6 数字接龙(标题难度10 知识难度6 目前只完成一半)
题目形貌
审题
思路:DFS
T7 拔河
题目形貌
审题
思路
总结

先附上结果,盼望达到不被喷的程度
T1 握手题目(标题难度1 知识难度1)

题目形貌

小蓝组织了一场算法交换集会,总共有50人参加了本次集会。在集会上,各人进行了握手交换。按照惯例他们每个人都要与除本身以外的其他全部人进行一次握手 (且仅有一次)。但有7个人,这7人相互之间没有进行握手 (但这 7人与除这 7人以外的全部人进行了握手)。叨教这些人之间一共进行了多少次握手?
注意A和B握手的同时也意味着B和A握手了,以是算作是一次握手。
知识点:握手

握手是很经典的数列1加到n-1的求和模型(一个人不能和本身握手),以是握手次数

由于7个人没有互相握手,以是总次数就等于

T2 小球反弹(标题难度7 知识难度3)

题目形貌

有一长方形,长为 343720 单位长度,宽为 233333 单位长度。在其内部左上角顶点有一小球 (无视其体积),其初速度如图所示且保持活动速率稳定,分解到长宽两个方向上的速率之比为 dx:dy=15:17。小球碰到长方形的边框时会发生反弹,每次反弹的入射角与反射角相等,因此小球会改变方向且保持速率稳定(假如小球刚好射向角落,则按入射方向原路返回)。从小球出发到其第一次回到左上角顶点这段时间里,小球活动的路程为多少单位长度?答案四舍五入保留两位小数。

审题

身为台球爱好者,感觉审题难度不大。
被高中物理折磨过的同道,看见这题也肯定习惯了。
经典的速度分解题目(不消科普速度分解题目吧,都是匀速!)
思路:模拟

没错我一开始想着模拟去做这题,计算路程长度。
写完了转向函数,我崩溃了。怎么进行下一步呢?真的一步一步来求解撞墙的时刻吗?
模拟大概是可以弄下去的,但是我目前没想到好方法。
  1. int dx[5]={0,1,-1,1,-1};
  2. int dy[5]={0,1,1,-1,-1};
  3. void trans()
  4. {
  5.         if(toward==1){//右下方向
  6.                 if(posx==a&&posy==b)
  7.                         toward=4;
  8.                 else if(posx==a)//右边的墙
  9.                         toward=3; //左下
  10.                 else if(posy==b)//下面的墙
  11.                         toward=2; //右上
  12.         }
  13.        
  14.         else if(toward==2){//右上方向
  15.                 if(posx==a&&posy==0)
  16.                         toward=3;
  17.                 else if(posx==a)//右边的墙
  18.                         toward=4;//左上
  19.                 else if(posy==0)//上面的墙
  20.                         toward=1;//右下
  21.         }
  22.        
  23.         else if(toward==3){//左下方向
  24.                 if(posx==0&&posy==b)
  25.                         toward=2;
  26.                 else if(posx==0)//左边的墙
  27.                         toward=1;//右下
  28.                 else if(posy==b)//下面的墙
  29.                         toward=4;//左上
  30.         }
  31.        
  32.         else if(toward==4){//左上方向
  33.                 if(posx==0&&posy==0)
  34.                         toward=1;
  35.                 else if(posx==0)//左边的墙
  36.                         toward=2;//右上
  37.                 else if(posy==0)//上面的墙
  38.                         toward=3;//左下
  39.         }
  40. }
复制代码
调整思路:解三角形

我们知道,小球的入射角反射角稳定,那么路径构成的直角三角形互相相似。
这个时候我萌生出了一种想法:无限延伸桌面......

因为根据题意,小球是一定能反弹回来的,反弹的路径就是已往的路径,那么只有撞到右上角顶点,才有大概反弹回左上角顶点
以是,延伸k个桌面,就需要满足
,此中a是343720。
数学小技巧:因为17是质数,以是要满足取余为0,k一定等于17的倍数
通过编程求解得k=17*52。
知道了k,那么不就知道去的长度了吗?整个来回是去的2倍,因此答案为:

T3 好数(标题难度4 知识难度3)

题目形貌

一个整数假如按从低位到高位的顺序,奇数位 (个位、百位、万位 ⋯⋯ ) 上的数字是奇数,偶数位 (十位、千位、十万位 ⋯⋯ ) 上的数字是偶数,我们就称之为 “好数”。
给定一个正整数 N,请计算从 1 到 N 一共有多少个好数。
审题

我们很容易想到,n的规模是10的7次方,那么1到n的全部数都去每一位验证是绝对超时的。有没有更加高效简单的方法推荐一下么?
思路:数学递推

我们通过摆列可以得到以下是好数:
13579
2123252729
4143454749
6163656769
8183858789
101103105107109
121123125127129
141143145147149
161163165167169
181183185187189
以此推下去,以是我一开始想的是这题可以递推做。
但是这么做下去有什么题目呢?反正有题目就对了哈哈
就比如189,你先把百位区间确定了,在100-200内,再确定十位区间,在80-90内,最后确定个位。反正我觉得实现很难,盼望有大佬能实现。
但是依照着这个思路,很容易想出另一种解法:
调整思路:动态规划

假如数n满足要求,那么抹掉最高位的数也得满足要求。比如789是好数,是因为89是好数,而7是奇数;89是好数是因为9是好数,8是偶数。
以是得到好数的判断条件:这个数抹掉最高位后的数也要是好数;且这个数的最高位若为奇数位,那么本身是奇数。
实现抹掉最高位数,那么需要计算n是几位数,这算是C语言根本功。
  1. int weishu(int x){
  2.         int count=0,temp=x;
  3.         while(temp){
  4.                 temp/=10;
  5.                 count++;
  6.         }
  7.         return count;
  8. }
复制代码
789留下89就相当于789%100
那么,引入一个afterpow,我们就能得到判断条件:
  1. int afterpow=(int)pow(10,count-1);
  2. if(dp[i%afterpow]==1&&isok(i,count,afterpow))
  3.         dp[i]=1;
  4. int isok(int x,int count,int afterpow)
  5. {
  6.         if(count%2==1){//奇数位
  7.                 if((x/afterpow)%2==1) return 1;
  8.                 else return 0;       
  9.         }
  10.         else if(count%2==0){//偶数位
  11.                 if((x/afterpow)%2==0) return 1;
  12.                 else return 0;       
  13.         }
  14. }
复制代码
但是这么做好像不符合答案。我漏了一些东西——0的情况。
我们思量这么一个数:10001,10001%10000=1,dp[1]=1。而万位的1是奇数,因此dp[10001]=1
可是,百位是0,也就是偶数!
通过一系列的推理判断,我发现要满足这么一个条件(具体怎么推的大概要点感觉,不容易学会)
假如count是偶数,那么第二个数不能是0;假如count是奇数,那么第三个数不能是0。
代码实现如下:
  1. if(count%2==1&&weishu(i%(afterpow/10))<count-2) continue;
  2. else if(count%2==0&&weishu(i%afterpow)<count-1) continue;
复制代码
那么肯定有人问了,比如假设count是偶数为什么不要求第二,第四,第六...都是0呢?为什么一个第二位就够了呢?
这就是因为动态规划是从1到n,它是线性往上走的,以是你只要包管前一个你问的数建立,那么背面的数就都能建立。
就比如1030005,我们知道因为百位是0,以是不是好数。但是看起来好像你只判断了万位的3并不是0(偶数),没有判断百位是0(偶数)以是他是不是dp置为1了?不是的,1030005保留030005后,我们看的是dp[30005]是否为1。然而这里在你的附加条件中已经给打下去了,他并不是好数,也就是dp[30005]=0,那么dp[1030005]自然为0。
总之反正意思就是涵盖了全部的情况(大概有些难以明白哈,笔者表达能力不好)。
T4 R格式(标题难度5 知识难度3)

题目形貌

小蓝最近在研究一种浮点数的表示方法:RR 格式。对于一个大于 0 的浮点数 dd,可以用 RR 格式的整数来表示。给定一个转换参数 nn,将浮点数转换为 RR 格式整数的做法是:
1.将浮点数乘以 2n2n;
2.四舍五入到最接近的整数。
一行输入一个整数 nn 和一个浮点数 dd,分别表示转换参数,和待转换的浮点数。
输出一行表示答案:dd 用 RR 格式表示出来的值。
审题

一开始我还不想写这题的审题,这么简单的审题!
然后写完了题解我破防了,四舍五入!四舍五入!四舍五入!我就是这个扣了一半分!
思路:高精度

假如不知道什么是高精度,发起在网站上找几篇去学以下。
客岁我只用了一个早操的时间看懂了高精度(咳咳,重点是早操)。
用高精度的思路,那么数是应该倒着放的。就比如12.3456倒着放是6543.21,否则乘法之后进位不好进。
我们再思量小数点的题目:在数值上,12.3456*2*2=123456*2*2/10000,因此我们要记录一下小数点位置pos,然后转数组的时候就不要带上小数点了。
  1. for(int i=0;i<len-1;i++){
  2.         if(s[len-1-i]=='.'){
  3.                 flag=1;
  4.                 pos=i;
  5.         }
  6.         a[i]=s[len-1-i-flag]-'0';
  7. }
复制代码
然后就是高精度乘法,乘2,进行n次。
最后我们思量进位的题目:
——写到这里我发现为什么我只拿到了一半分,我以为是向上取整,审错标题啦!
我们可以草稿纸比划一下,推理得到a[pos]就是整个数的个位数
比如12.3456的pos=4,假设乘2的0次方(也就是1)后得到a数组是654321,a[4]=2。
讨论a[pos-1],小于5数组稳定,大于等于5那么a[pos]++。
假如a[pos]刚好是9,那么加1变成10,恭喜你还要做一次高精度加法。
为什么不直接把1加在a[pos+1]上呢?——万一a[pos+1]=9怎么办?以是就是for要加到底。
  1. if(a[pos]==9){//最后一个数字是9
  2.         a[pos]++;
  3.         for(int i=pos;i<=1500;i++){
  4.                 if(a[i]>=10){
  5.                         a[i+1]+=a[i]/10;
  6.                         a[i]=a[i]%10;
  7.                 }
  8.         }
  9. }
  10. else
  11.         a[pos]++;
  12.        
  13. int top=1500;
  14. while(a[top]==0) top--;
  15. while(top>=pos){
  16.         cout<<a[top];
  17.         top--;
  18. }
复制代码
这题高精度加法乘法都用上了,考的照旧比较全面。
T6 数字接龙(标题难度10 知识难度6 目前只完成一半)

题目形貌


审题

输出一条路径,而且照旧字典序最小——
就差DFS明写在这里了
然后是四个条件
A.8个方向 B.满足数列 C.每个点1次 D.路径不可交错
思路:DFS

DFS和BFS的视线有许多共同点,可以参考我写的BFS:
BFS(广度优先搜索)的明白与代码实现-CSDN博客
初始化:
8个方向按照先后顺序。
用栈来实现生存路径。
数组a记录数列在图的顺序,数组s标记是否有遍历。
  1. int stack[105]={0};
  2. int top=1,nownum=0,flag=0;
  3. int dx[8]={-1,-1, 0, 1, 1, 1, 0,-1};
  4. int dy[8]={ 0, 1, 1, 1, 0,-1,-1,-1};
  5. int a[15][15]={0};
  6. bool s[15][15]={0};
复制代码
递归DFS:
8个方向的搜索,每次搜完后需要回溯
假如越界,那么过
假如去了已标记的地方,那么过
假如顺序不符合数列,那么过
停止条件判断:
假如到了底,也就是(n,n),假如全部的点未完全覆盖,也就是s[j]还有0,那么错误。
真的符合题意了,那么先输出路径,然后flag置为1,主函数中flag假如是0,那么输出-1。
以是,本题“路径不可交错”这个点我还没想出来怎样实现,盼望有大佬能指点!
不实现这个也过了75%的测试点。
  1. void dfs(int x,int y){//缺陷:无法处理交叉
  2.         if(x==n&&y==n){
  3.                 for(int i=1;i<=n;i++){
  4.                         for(int j=1;j<=n;j++){
  5.                                 if(!s[i][j])
  6.                                         return;
  7.                         }
  8.                 }//如果有未完全覆盖的路线,打掉
  9.                
  10.                 if(flag==0){
  11.                         for(int i=1;i<=n*n-1;i++)
  12.                                 cout<<stack[i];
  13.                 }
  14.                 flag=1;
  15.                 return ;
  16.         }
  17.        
  18.         for(int i=0;i<=7;i++){
  19.                 int px=x+dx[i],py=y+dy[i];
  20.                
  21.                 if(px<1||px>n||py<1||py>n||s[px][py])//越界或标记过
  22.                         continue;
  23.                 if(nownum!=k-1){//nownum不是k-1的时候
  24.                         if(a[px][py]!=nownum+1)//下一个位置不是0,打掉
  25.                                 continue;
  26.                 }
  27.                 else if(nownum==k-1){//nownum是k-1
  28.                         if(a[px][py]!=0)//下一个位置不是0,打掉
  29.                                 continue;
  30.                 }
  31.                
  32.                 int temp=nownum;//存储过往
  33.                
  34.                 nownum=a[px][py];
  35.                 stack[top++]=i;
  36.                 s[px][py]=1;
  37.                
  38.                 dfs(px,py);
  39.                
  40.                 stack[--top]=0;
  41.                 nownum=temp;
  42.                 s[px][py]=0;
  43.         }
  44.         return ;
  45. }
复制代码
T7 拔河

题目形貌

小明是学校里的一名老师,他带的班级共有 n 名同学,第 i 名同学力量值为 
。在闲暇之余,小明决定在班级里组织一场拔河比赛。
为了包管比赛的两边实力尽大概相近,需要在这 nn 名同学中挑选出两个队伍,队伍内的同学编号一连:
,此中 

两个队伍的人数不必雷同,但是需要让队伍内的同学们的力量值之和尽大概相近。请计算着力量值之和差距最小的挑选队伍的方式。
审题

这题我也是完美地审错了题意。
A.队伍内编号一连,编号一连,编号一连! B.两边绝对值差最小。
以是实质上就是数列子序列的题目,求2个子序列使差值最小。
我审题觉得就是这种类型的题:P2392 kkksc03考前暂时抱佛脚 - 洛谷
给定一个数列,区分成两半,怎样使两边的差值最小?(编号不一定一连)
假如是按照我的明白,那么这题的解法就是递归摆列,和第6题DFS思路很像:
(以是写这些只是为了复习一下摆列,不是错误引导,我写到了就是我赚了哈哈哈)
  1. void dfs(long long depth){
  2.         if(depth>n){
  3.                 long long temp=0;
  4.                 if(rightn-leftn<0) temp=leftn-rightn;
  5.                 else temp=rightn-leftn;
  6.                 res=min(res,temp);
  7.                 return ;
  8.         }
  9.        
  10.         leftn+=a[depth];
  11.         dfs(depth+1);
  12.         leftn-=a[depth];
  13.         rightn+=a[depth];
  14.         dfs(depth+1);
  15.         rightn-=a[depth];
  16. }
复制代码
思路

我还没学会。。。
总结

写完第二和第三题的题解后,有一个最直观的感受:
遇见题目要多分析,探求本质核心,而不是一味地模拟模拟。
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张春

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表