洛谷 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 n−1 站),都满足此规律。现给出的条件是:共有 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 1≤a≤20, 1 ≤ x ≤ n ≤ 20 1 \leq x \leq n \leq 20 1≤x≤n≤20, 1 ≤ m ≤ 2 × 1 0 4 1 \leq m \leq 2 \times 10^4 1≤m≤2×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 <stdio.h>
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截图

文章讲述了如何通过分析数学规律解决NOIP1998提高组的车站问题,涉及兔子数列的应用、数组的构建和递推计算方法,最终确定任意车站上车人数。
375

被折叠的 条评论
为什么被折叠?



