拼数与车站思路讲解
文章目录
前言
哈喽,各位小伙伴大家好!今天小编给大家带来两道有趣的数学规律题(拼数和车站),这需要我们具备一定的观察能力,这在编程思维中是不可或缺的。话不多说,又是向大厂进发的一天,冲!
一.拼数
1.1题目
题目意思简单来说就是,将给定的n个数拼成一个数,确保拼出来的数是最大的。
1.2思路分析
题目看起来很复杂,其实一点也不复杂。大家都很容易想到谁的首个数字大谁在前面,但是如果首位数字相同呢?这时候有小伙伴说那就比下一位,如果下一位也相同呢?这样比是不是效率太低了?其实是我们把简单的问题复杂化了。首位数字相同时,我们只需分别计算出两种顺序的结果就可以了,哪个结果大就按照那个顺序排即可。计算时我们需要知道两个数的位数,所以我们可以写个函数统计每个数的位数,再写一个函数得出每个数字的首位数字。我们在创建一个三列的二维数组。每行存放首位数字,位数,数字。再用冒泡排序对数组进行排序,如果首位数字不同则直接按首位数字大小排序,否则则按计算结果排序。注意,记得每行的三个元素都要交换哦。
1.3统计次数函数
统计次数函数我们用写个while循环,每次循环用一个变量记录次数,再对形参数字进行除10。当形参==0时结束循环。
int counts(int a)
{
int c = 0;
while (a != 0)
{
c++;//记录次数
a /= 10;
}
return c;
}
1.4首数字函数
同理,首位数字函数我们也写个while循环,每次循环用一个变量记录当前数字,再对形参数字进行除10。当变量记录的形参等于首位数字时,形参除10==0,结束循环。此时变量里面就是首位数字。
int count(int a)
{
int c = 0;
while (a != 0)
{
c = a;//存放当前数字
a /= 10;
}
return c;
}
1.5冒泡排序
冒泡排序动画演示
大家可以到看 冒泡排序就是进行 n-1趟的排序, 每次排序从左到右或从右到左进行 相邻两数的比较, 每次比较将最大或最小的数排好序,进行 n-1趟排序即可排序完成。我们用 for循环控制趟数,里面嵌套一层 for循环控制比较次数,再用 if判断是否满足 交换条件,满足则 进行交换。
for (int i = 0; i < n; i++)
{
int c = 0;
for (int j = 0; j < n - 1 - i; j++)
{
if (a[j][1] > a[j + 1][1])//首位数字不同
{
c = a[j][1];
a[j][1] = a[j + 1][1];
a[j + 1][1] = c;
c = a[j][0];
a[j][0] = a[j + 1][0];
a[j + 1][0] = c;
c = a[j][2];
a[j][2] = a[j + 1][2];
a[j + 1][2] = c;//交换
}
else if (a[j][1] == a[j + 1][1])//首位数字相同
{
if (a[j][0]*pow(10,a[j+1][2])+a[j+1][0]> a[j+1][0]*pow(10, a[j][2]) + a[j][0])//比较
{
c = a[j][1];
a[j][1] = a[j + 1][1];
a[j + 1][1] = c;
c = a[j][0];
a[j][0] = a[j + 1][0];
a[j + 1][0] = c;
c = a[j][2];
a[j][2] = a[j + 1][2];
a[j + 1][2] = c;//交换
}
}
}
}
- 变量交换
这里讲解一下交换的过程,两个变量交换的原理,就是创建一个变量存放其中一个变量的数据,再将已经存放数据的变量数据改为另一个变量的数据,最后将保存的数据赋值给另一个变量即可。注意,本题三个元素都要交换。
1.6遍历输出
最后,将排序好的数组输出即可。注意我们排的是升序,所以是从i=n-1开始输出。
for (int i = n - 1; i >= 0; i--)
{
printf("%d", a[i][0]);//升序从n-1开始输出
}
二.车站
2.1题目
2.2题目解释
画了个图,方便大家理解。a是第一站上车人数,b是第二站上车人数,从第三站开始每站上车人数等于前两站上车人数之和,下车人数等于上一站上车人数。给出a,车站数n,终点站下车人数m,求x车站开出时 车上有多少人。
2.3思路分析
大家只要仔细观察就会发现,其实解题的关键就是求出b,只要求出b这样每站上下车人数都可以知道了。问题自然迎刃而解啦。那怎么求b呢?题目给我们那么多参数肯定是有原因的。大家看仔细观察思路图就可知道要求出m只需要三个数就可以了,我们在提取公因式a和b就可以得出一条等式,根据这条等式就可以求出b了。那我们就可以创建一个数组c来存放每个车站b的个数,给前两个元素初始化为0和1,之后for循环递推出每个车站b的个数。同理,创建一个数组c1来存放每个车站a的个数,给前两个元素初始化为1和0,之后for循环递推出每个车站a的个数。之后用公式求出b的值即可,在套用公式即可求出x车站开出时车上的人数,注意下标的区分,这里是n-1。
2.4创建数组
为了得出每个车站a和b的个数,我们用数组存放每个车站用多少个a和b。根据题目信息给前面两个元素初始化,递推得出全部车站的信息。
int c[20] = {0,1};//记录b个数数组
int c1[20] = { 1,0 };//记录a个数数组
for(int i=2;i < 20-1;i++)
{
c[i] = c[i - 1] + c[i - 2];//统计b个数
}
for (int i = 2; i < 20-1; i++)
{
c1[i] = c1[i - 1] + c1[i - 2];//统计a个数
}
2.5公式计算
套用公式求出b后直接再套用公式求出x车站开出后车上的人数。注意,区分求b时的下标和求车站开出时的下标。
int b = (m-(c1[n-2]+1)*a)/(c[n-2]-1);//b=m-(a*a的个数)/b的个数
printf("%d", ((c1[x - 1] + 1) * a) +((c[x - 1] - 1) * b));
2.6情况区分
大家注意x的取值范围。我们需要分情况讨论,如果x小于等于2,车上人数一直是a,直接输出即可。如果x==n,终点站开出时乘客全部下车了,车上没人,所以输出0。其他情况就是直接用我们的公式计算可以啦。这也告诉我们要养成细心观察和严谨的好习惯。
if (x <= 2)
printf("%d", a);//前两站的人数都是a直接输出即可
else if (x == n)//n为终点站,全部下车,车上人数为0;
printf("%d", 0);
else
{
//20是因为题目最多由20个车站
int c[20] = {0,1};//记录b个数数组
int c1[20] = { 1,0 };//记录a个数数组
for(int i=2;i < 20-1;i++)
{
c[i] = c[i - 1] + c[i - 2];//统计b个数
}
for (int i = 2; i < 20-1; i++)
{
c1[i] = c1[i - 1] + c1[i - 2];//统计a个数
}
int b = (m-(c1[n-2]+1)*a)/(c[n-2]-1);//b=m-(a*a的个数)/b的个数
printf("%d", ((c1[x - 1] + 1) * a) +((c[x - 1] - 1) * b));
}
三.源码
3.1拼数
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int counts(int a)
{
int c = 0;
while (a != 0)
{
c++;//记录次数
a /= 10;
}
return c;
}
int count(int a)
{
int c = 0;
while (a != 0)
{
c = a;//存放当前数字
a /= 10;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int a[1000][3] = {0};//创建数组
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i][0]);
a[i][1] = count(a[i][0]);//存放首位数字
a[i][2] = counts(a[i][0]);//存放位数
}
for (int i = 0; i < n; i++)
{
int c = 0;
for (int j = 0; j < n - 1 - i; j++)
{
if (a[j][1] > a[j + 1][1])//首位数字不同
{
c = a[j][1];
a[j][1] = a[j + 1][1];
a[j + 1][1] = c;
c = a[j][0];
a[j][0] = a[j + 1][0];
a[j + 1][0] = c;
c = a[j][2];
a[j][2] = a[j + 1][2];
a[j + 1][2] = c;//交换
}
else if (a[j][1] == a[j + 1][1])//首位数字相同
{
if (a[j][0]*pow(10,a[j+1][2])+a[j+1][0]> a[j+1][0]*pow(10, a[j][2]) + a[j][0])//比较
{
c = a[j][1];
a[j][1] = a[j + 1][1];
a[j + 1][1] = c;
c = a[j][0];
a[j][0] = a[j + 1][0];
a[j + 1][0] = c;
c = a[j][2];
a[j][2] = a[j + 1][2];
a[j + 1][2] = c;//交换
}
}
}
}
for (int i = n - 1; i >= 0; i--)
{
printf("%d", a[i][0]);//升序从n-1开始输出
}
return 0;//华丽结束!
}
3.2车站
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a, n, m, x;
scanf("%d%d%d%d", &a, &n, &m, &x);//接收参数
if (x <= 2)
printf("%d", a);//前两站的人数都是a直接输出即可
else if (x == n)//n为终点站,全部下车,车上人数为0;
printf("%d", 0);
else
{
//20是因为题目最多由20个车站
int c[20] = {0,1};//记录b个数数组
int c1[20] = { 1,0 };//记录a个数数组
for(int i=2;i < 20-1;i++)
{
c[i] = c[i - 1] + c[i - 2];//统计b个数
}
for (int i = 2; i < 20-1; i++)
{
c1[i] = c1[i - 1] + c1[i - 2];//统计a个数
}
int b = (m-(c1[n-2]+1)*a)/(c[n-2]-1);//b=m-(a*a的个数)/b的个数
printf("%d", ((c1[x - 1] + 1) * a) +((c[x - 1] - 1) * b));
}
return 0;//华丽结束
}
后言
这两道题目主要考察我们的观察和总结归纳能力,这对我们的编程思想提升大有卑益。希望看完后,各位小伙伴都能有所收获!今天就分享到这,咱们下期见!