拼数与车站思路讲解

拼数与车站思路讲解

前言

哈喽,各位小伙伴大家好!今天小编给大家带来两道有趣的数学规律题(拼数车站),这需要我们具备一定的观察能力,这在编程思维中是不可或缺的。话不多说,又是向大厂进发的一天,冲!

一.拼数

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;//华丽结束
}

后言

这两道题目主要考察我们的观察和总结归纳能力,这对我们的编程思想提升大有卑益。希望看完后,各位小伙伴都能有所收获!今天就分享到这,咱们下期见!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大白的编程日记.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值