洛谷 P1011 车站 题解(C语言)

洛谷 P1011 车站 题解

题目

[NOIP1998 提高组] 车站

题目描述

火车从始发站(称为第 1 1 1 站)开出,在始发站上车的人数为 a a a,然后到达第 2 2 2 站,在第 2 2 2 站有人上、下车,但上、下车的人数相同,因此在第 2 2 2 站开出时(即在到达第 3 3 3 站之前)车上的人数保持为 a a a 人。从第 3 3 3 站起(包括第 3 3 3 站)上、下车的人数有一定规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第 n − 1 n-1 n1 站),都满足此规律。现给出的条件是:共有 n n n 个车站,始发站上车的人数为 a a a,最后一站下车的人数是 m m m(全部下车)。试问 x x x 站开出时车上的人数是多少?

输入格式

输入只有一行四个整数,分别表示始发站上车人数 a a a,车站数 n n n,终点站下车人数 m m m 和所求的站点编号 x x x

输出格式

输出一行一个整数表示答案:从 x x x 站开出时车上的人数。

样例 #1
样例输入 #1
5 7 32 4
样例输出 #1
13
提示

对于全部的测试点,保证 1 ≤ a ≤ 20 1 \leq a \leq 20 1a20 1 ≤ x ≤ n ≤ 20 1 \leq x \leq n \leq 20 1xn20 1 ≤ m ≤ 2 × 1 0 4 1 \leq m \leq 2 \times 10^4 1m2×104

NOIP1998 提高组 第一题

思路分析

此题本质是一个找规律的数学问题,先列表格对前6站进行分析,便能很轻松找到规律

站名 第一站 第二站 第三站 第四站 第五站 第六站
上车人数 a k a+k a+2k 2a+3k 3a+5k
下车人数 0 k k a+k a+2k 2a+3k
总增加人数 a 0 a k a+k a+2k
车上现有人数 a a 2a 2a+k 3a+2k 4a+4k

不难发现规律

1、将每一站的上车人数定义为一个数组arr,是一个兔子数列(从第三项起每一项等于前两项之和)

2、而将每一站乘客上下车后车上的现有人数定义为一个数组brr,这个数组也有规律,即:brr[i]=brr[i-1]+arr[i-2](前一站车上人数,加本站增加人数)

3、arr和brr数组每一项都是有a和k的多项式构成,只是a和k前的系数不一样,那么我们可以分别把a和k拿出来单独研究

arr数组每一项中a的系数(arr_a[]) 1 0 1 1 2 3
arr数组每一项中k的系数(arr_k[]) 0 1 1 2 3 5
brr数组每一项中a的系数(brr_a[]) 1 1 2 2 3 4
brr数组每一项中k的系数(brr_k[]) 0 0 0 1 2 4

不难发现规律:

1、arr_a[]和arr_k[]这两个数组都是兔子数列

2、brr_a[i]=brr_a[i-1]+arr_a[i-2]

​ brr_k[i]=brr_k[i-1]+arr_k[i-2]

3、综上可得出公式:brr[i]=brr[i-1]+arr[i-2]=(brr_a[i-1] + arr_a[i-2])*a+(brr_k[i-1] + arr_k[i-2])*k

先将这四个数组初始化

int arr_a[20] = { 0 };//arr每项a的系数
int arr_k[20] = { 0 };//arr每项b的系数
int brr_a[20] = { 0 };//brr每项a的系数
int brr_k[20] = { 0 };//brr每项k的系数
arr_a[0] = 1;
arr_a[1] = 0;
arr_k[0] = 0;
arr_k[1] = 1;
brr_a[0] = 1;
brr_a[1] = 1;
brr_k[0] = 0;
brr_k[1] = 0;
for (i = 2; i <= n - 2; i++)
{
	arr_a[i] = arr_a[i - 1] + arr_a[i - 2];
	arr_k[i] = arr_k[i - 1] + arr_k[i - 2];
	brr_a[i] = brr_a[i - 1] + arr_a[i - 2];
	brr_k[i] = brr_k[i - 1] + arr_k[i - 2];
}

此题突破口:最后一站下车的人数是 m(全部下车)

意味着倒数第二站乘客上下车后车上总人数为m,也就是brr[n-2]=m

由推导的公式可知**brr[n-2]=brr[n-3]+arr[n-4]=(brr_a[n-3] + arr_a[n-4])a+(brr_k[n-3] + arr_k[n-4])k

a的值已知,便可求出k的值,求出k的值后,变可求出每站上下车后的总人数

求出k的值

int num_a = brr_a[n - 3] + arr_a[n - 4];
int num_k = brr_k[n - 3] + arr_k[n - 4];
k = (m - num_a * a) / num_k;

求出任意x站车上总人数

int num = (brr_a[x - 2] + arr_a[x - 3]) * a + (brr_k[x - 2] + arr_k[x - 3]) * k;

完整代码

#include 
int main()
{
	int a, n, m, x;
	int i, k;
	scanf("%d %d %d %d", &a, &n, &m, &x);
	//第一站上车人数为a,车站数为n,倒数第二站车上总人数为m
	//假设第二站上下车人数相等为k
	//arr数组表示每站上车的人数,brr表示每站上下车后车上的人数
	int arr_a[20] = { 0 };//arr每项a的系数
	int arr_k[20] = { 0 };//arr每项b的系数
	int brr_a[20] = { 0 };//brr每项a的系数
	int brr_k[20] = { 0 };//brr每项k的系数
	arr_a[0] = 1;
	arr_a[1] = 0;
	arr_k[0] = 0;
	arr_k[1] = 1;
	brr_a[0] = 1;
	brr_a[1] = 1;
	brr_k[0] = 0;
	brr_k[1] = 0;
	for (i = 2; i <= n - 2; i++)
	{
		arr_a[i] = arr_a[i - 1] + arr_a[i - 2];
		arr_k[i] = arr_k[i - 1] + arr_k[i - 2];
		brr_a[i] = brr_a[i - 1] + arr_a[i - 2];
		brr_k[i] = brr_k[i - 1] + arr_k[i - 2];
	}
	int num_a = brr_a[n - 3] + arr_a[n - 4];
	int num_k = brr_k[n - 3] + arr_k[n - 4];
	k = (m - num_a * a) / num_k;

	int num = (brr_a[x - 2] + arr_a[x - 3]) * a + (brr_k[x - 2] + arr_k[x - 3]) * k;
	printf("%d", num);
	return 0;
}

附:AC截图

洛谷 P1011 车站 题解(C语言)_第1张图片

你可能感兴趣的:(c语言,算法,开发语言)