【题目链接】
【题目考点】
1. 枚举
2. 递推
【解题思路】
设在第2站上车b人
列表找规律:
站点 | 上车人数(u) | 下车人数(d) | 从第i站出发时车上人数(p) |
---|---|---|---|
1 | a | 0 | a |
2 | b | b | a |
3 | a+b | b | 2a |
4 | a+2b | a+b | 2a+b |
5 | 2a+3b | a+2b | 3a+2b |
… |
记第i站上车人数为 u i u_i ui,下车人数为 d i d_i di,从第i站出发时车上人数为 p i p_i pi。
题目所求的是在第x站出发时车上的人数,即 p x p_x px,实际就是要求p数组。
当 i ≥ 3 i\ge 3 i≥3时有规律:
u i = u i − 1 + u i − 2 u_i=u_{i-1}+u_{i-2} ui=ui−1+ui−2
d i = u i − 1 d_i=u_{i-1} di=ui−1
p i = p i − 1 + u i − d i = p i − 1 + u i − 2 p_i=p_{i-1}+u_i-d_i=p_{i-1}+u_{i-2} pi=pi−1+ui−di=pi−1+ui−2
已知第n站下车m人,即第n-1站出发时车上有m人,即 p n − 1 = m p_{n-1} = m pn−1=m
这里不方便得到以b为未知数的方程。如果用枚举算法来做的话,其实也不是一定要把方程列出来。
这里可以枚举b的值。
关于b的范围,最小为0。根据题目提供的条件,n最小值为4。
- 当n为4时, m = p 3 = 2 a m=p_3=2a m=p3=2a,此时b的值不起作用,b可以在任意范围内枚举。
- 当 n > 4 n>4 n>4时,根据上述规律可以看出,一定有 m = p n − 1 > b m=p_{n-1} > b m=pn−1>b
因此把b的最大值设为m-1即可。
- 枚举对象:b
- 枚举范围: 0 ≤ b ≤ m 0\le b \le m 0≤b≤m
- 判断条件:
已知 u 1 = a , u 2 = b u_1=a, u_2=b u1=a,u2=b,递推关系 u i = u i − 1 + u i − 2 u_i=u_{i-1}+u_{i-2} ui=ui−1+ui−2。
已知 p 2 = a p_2=a p2=a,递推关系 p i = p i − 1 + u i − 2 p_i=p_{i-1}+u_{i-2} pi=pi−1+ui−2
递推求出 p n − 1 p_{n-1} pn−1,判断是否满足 p n − 1 = m p_{n-1}=m pn−1=m。
如果满足,则找到了解,输出 p x p_x px
复杂度分析:b循环m次,m最大为 1 0 4 10^4 104,递推最大循环接近n次,n最大为15,因此总循环次数为 1 0 4 ∗ 15 ≈ 1 0 5 10^4*15\approx10^5 104∗15≈105数量级,可以接受。
【题解代码】
解法1:枚举
#include <bits/stdc++.h>
using namespace std;
#define N 20
int main()
{
int a, n, m, x, u[N], p[N];//u[i]:第i站上车的人数 p[i]:第i站车出发时车上的人数
cin >> a >> n >> m >> x;
u[1] = p[2] = a;
for(int b = 0; b < m; ++b)
{
u[2] = b;
for(int i = 3; i <= n-1; ++i)
{
u[i] = u[i-1] + u[i-2];
p[i] = p[i-1] + u[i-2];
}
if(p[n-1] == m)
{
cout << p[x];
return 0;
}
}
return 0;
}