目录
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。小球碰到长方形的边框时会发生反弹,每次反弹的入射角与反射角相等,因此小球会改变方向且保持速率稳定(假如小球刚好射向角落,则按入射方向原路返回)。从小球出发到其第一次回到左上角顶点这段时间里,小球活动的路程为多少单位长度?答案四舍五入保留两位小数。
审题
身为台球爱好者,感觉审题难度不大。
被高中物理折磨过的同道,看见这题也肯定习惯了。
经典的速度分解题目(不消科普速度分解题目吧,都是匀速!)
思路:模拟
没错我一开始想着模拟去做这题,计算路程长度。
写完了转向函数,我崩溃了。怎么进行下一步呢?真的一步一步来求解撞墙的时刻吗?
模拟大概是可以弄下去的,但是我目前没想到好方法。
- int dx[5]={0,1,-1,1,-1};
- int dy[5]={0,1,1,-1,-1};
- void trans()
- {
- if(toward==1){//右下方向
- if(posx==a&&posy==b)
- toward=4;
- else if(posx==a)//右边的墙
- toward=3; //左下
- else if(posy==b)//下面的墙
- toward=2; //右上
- }
-
- else if(toward==2){//右上方向
- if(posx==a&&posy==0)
- toward=3;
- else if(posx==a)//右边的墙
- toward=4;//左上
- else if(posy==0)//上面的墙
- toward=1;//右下
- }
-
- else if(toward==3){//左下方向
- if(posx==0&&posy==b)
- toward=2;
- else if(posx==0)//左边的墙
- toward=1;//右下
- else if(posy==b)//下面的墙
- toward=4;//左上
- }
-
- else if(toward==4){//左上方向
- if(posx==0&&posy==0)
- toward=1;
- else if(posx==0)//左边的墙
- toward=2;//右上
- else if(posy==0)//上面的墙
- toward=3;//左下
- }
- }
复制代码 调整思路:解三角形
我们知道,小球的入射角反射角稳定,那么路径构成的直角三角形互相相似。
这个时候我萌生出了一种想法:无限延伸桌面......
因为根据题意,小球是一定能反弹回来的,反弹的路径就是已往的路径,那么只有撞到右上角顶点,才有大概反弹回左上角顶点。
以是,延伸k个桌面,就需要满足,此中a是343720。
数学小技巧:因为17是质数,以是要满足取余为0,k一定等于17的倍数。
通过编程求解得k=17*52。
知道了k,那么不就知道去的长度了吗?整个来回是去的2倍,因此答案为:
T3 好数(标题难度4 知识难度3)
题目形貌
一个整数假如按从低位到高位的顺序,奇数位 (个位、百位、万位 ⋯⋯ ) 上的数字是奇数,偶数位 (十位、千位、十万位 ⋯⋯ ) 上的数字是偶数,我们就称之为 “好数”。
给定一个正整数 N,请计算从 1 到 N 一共有多少个好数。
审题
我们很容易想到,n的规模是10的7次方,那么1到n的全部数都去每一位验证是绝对超时的。有没有更加高效简单的方法推荐一下么?
思路:数学递推
我们通过摆列可以得到以下是好数:
1 | 3 | 5 | 7 | 9 | 21 | 23 | 25 | 27 | 29 | 41 | 43 | 45 | 47 | 49 | 61 | 63 | 65 | 67 | 69 | 81 | 83 | 85 | 87 | 89 | 101 | 103 | 105 | 107 | 109 | 121 | 123 | 125 | 127 | 129 | 141 | 143 | 145 | 147 | 149 | 161 | 163 | 165 | 167 | 169 | 181 | 183 | 185 | 187 | 189 | 以此推下去,以是我一开始想的是这题可以递推做。
但是这么做下去有什么题目呢?反正有题目就对了哈哈
就比如189,你先把百位区间确定了,在100-200内,再确定十位区间,在80-90内,最后确定个位。反正我觉得实现很难,盼望有大佬能实现。
但是依照着这个思路,很容易想出另一种解法:
调整思路:动态规划
假如数n满足要求,那么抹掉最高位的数也得满足要求。比如789是好数,是因为89是好数,而7是奇数;89是好数是因为9是好数,8是偶数。
以是得到好数的判断条件:这个数抹掉最高位后的数也要是好数;且这个数的最高位若为奇数位,那么本身是奇数。
实现抹掉最高位数,那么需要计算n是几位数,这算是C语言根本功。
- int weishu(int x){
- int count=0,temp=x;
- while(temp){
- temp/=10;
- count++;
- }
- return count;
- }
复制代码 789留下89就相当于789%100
那么,引入一个afterpow,我们就能得到判断条件:
- int afterpow=(int)pow(10,count-1);
- if(dp[i%afterpow]==1&&isok(i,count,afterpow))
- dp[i]=1;
- int isok(int x,int count,int afterpow)
- {
- if(count%2==1){//奇数位
- if((x/afterpow)%2==1) return 1;
- else return 0;
- }
- else if(count%2==0){//偶数位
- if((x/afterpow)%2==0) return 1;
- else return 0;
- }
- }
复制代码 但是这么做好像不符合答案。我漏了一些东西——0的情况。
我们思量这么一个数:10001,10001%10000=1,dp[1]=1。而万位的1是奇数,因此dp[10001]=1
可是,百位是0,也就是偶数!
通过一系列的推理判断,我发现要满足这么一个条件(具体怎么推的大概要点感觉,不容易学会)
假如count是偶数,那么第二个数不能是0;假如count是奇数,那么第三个数不能是0。
代码实现如下:
- if(count%2==1&&weishu(i%(afterpow/10))<count-2) continue;
- 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,然后转数组的时候就不要带上小数点了。
- for(int i=0;i<len-1;i++){
- if(s[len-1-i]=='.'){
- flag=1;
- pos=i;
- }
- a[i]=s[len-1-i-flag]-'0';
- }
复制代码 然后就是高精度乘法,乘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要加到底。
- if(a[pos]==9){//最后一个数字是9
- a[pos]++;
- for(int i=pos;i<=1500;i++){
- if(a[i]>=10){
- a[i+1]+=a[i]/10;
- a[i]=a[i]%10;
- }
- }
- }
- else
- a[pos]++;
-
- int top=1500;
- while(a[top]==0) top--;
- while(top>=pos){
- cout<<a[top];
- top--;
- }
复制代码 这题高精度加法乘法都用上了,考的照旧比较全面。
T6 数字接龙(标题难度10 知识难度6 目前只完成一半)
题目形貌
审题
输出一条路径,而且照旧字典序最小——
就差DFS明写在这里了
然后是四个条件
A.8个方向 B.满足数列 C.每个点1次 D.路径不可交错
思路:DFS
DFS和BFS的视线有许多共同点,可以参考我写的BFS:
BFS(广度优先搜索)的明白与代码实现-CSDN博客
初始化:
8个方向按照先后顺序。
用栈来实现生存路径。
数组a记录数列在图的顺序,数组s标记是否有遍历。
- int stack[105]={0};
- int top=1,nownum=0,flag=0;
- int dx[8]={-1,-1, 0, 1, 1, 1, 0,-1};
- int dy[8]={ 0, 1, 1, 1, 0,-1,-1,-1};
- int a[15][15]={0};
- bool s[15][15]={0};
复制代码 递归DFS:
8个方向的搜索,每次搜完后需要回溯
假如越界,那么过
假如去了已标记的地方,那么过
假如顺序不符合数列,那么过
停止条件判断:
假如到了底,也就是(n,n),假如全部的点未完全覆盖,也就是s[j]还有0,那么错误。
真的符合题意了,那么先输出路径,然后flag置为1,主函数中flag假如是0,那么输出-1。
以是,本题“路径不可交错”这个点我还没想出来怎样实现,盼望有大佬能指点!
不实现这个也过了75%的测试点。
- void dfs(int x,int y){//缺陷:无法处理交叉
- if(x==n&&y==n){
- for(int i=1;i<=n;i++){
- for(int j=1;j<=n;j++){
- if(!s[i][j])
- return;
- }
- }//如果有未完全覆盖的路线,打掉
-
- if(flag==0){
- for(int i=1;i<=n*n-1;i++)
- cout<<stack[i];
- }
- flag=1;
- return ;
- }
-
- for(int i=0;i<=7;i++){
- int px=x+dx[i],py=y+dy[i];
-
- if(px<1||px>n||py<1||py>n||s[px][py])//越界或标记过
- continue;
- if(nownum!=k-1){//nownum不是k-1的时候
- if(a[px][py]!=nownum+1)//下一个位置不是0,打掉
- continue;
- }
- else if(nownum==k-1){//nownum是k-1
- if(a[px][py]!=0)//下一个位置不是0,打掉
- continue;
- }
-
- int temp=nownum;//存储过往
-
- nownum=a[px][py];
- stack[top++]=i;
- s[px][py]=1;
-
- dfs(px,py);
-
- stack[--top]=0;
- nownum=temp;
- s[px][py]=0;
- }
- return ;
- }
复制代码 T7 拔河
题目形貌
小明是学校里的一名老师,他带的班级共有 n 名同学,第 i 名同学力量值为 。在闲暇之余,小明决定在班级里组织一场拔河比赛。
为了包管比赛的两边实力尽大概相近,需要在这 nn 名同学中挑选出两个队伍,队伍内的同学编号一连:和,此中 。
两个队伍的人数不必雷同,但是需要让队伍内的同学们的力量值之和尽大概相近。请计算着力量值之和差距最小的挑选队伍的方式。
审题
这题我也是完美地审错了题意。
A.队伍内编号一连,编号一连,编号一连! B.两边绝对值差最小。
以是实质上就是数列子序列的题目,求2个子序列使差值最小。
我审题觉得就是这种类型的题:P2392 kkksc03考前暂时抱佛脚 - 洛谷
给定一个数列,区分成两半,怎样使两边的差值最小?(编号不一定一连)
假如是按照我的明白,那么这题的解法就是递归摆列,和第6题DFS思路很像:
(以是写这些只是为了复习一下摆列,不是错误引导,我写到了就是我赚了哈哈哈)
- void dfs(long long depth){
- if(depth>n){
- long long temp=0;
- if(rightn-leftn<0) temp=leftn-rightn;
- else temp=rightn-leftn;
- res=min(res,temp);
- return ;
- }
-
- leftn+=a[depth];
- dfs(depth+1);
- leftn-=a[depth];
- rightn+=a[depth];
- dfs(depth+1);
- rightn-=a[depth];
- }
复制代码 思路
我还没学会。。。
总结
写完第二和第三题的题解后,有一个最直观的感受:
遇见题目要多分析,探求本质核心,而不是一味地模拟模拟。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |