题目描述
火车从始发站(称为第 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 站开出时车上的人数。
输入输出样例
输入
5 7 32 4
输出
13
说明/提示
对于全部的测试点,保证 1 ≤ a ≤ 20 1≤a≤20 1≤a≤20, 1 ≤ x ≤ n ≤ 20 1≤x≤n≤20 1≤x≤n≤20, 1 ≤ m ≤ 2 × 1 0 4 1≤m≤2×10^{4} 1≤m≤2×104。
题目来源:洛谷P1011 [NOIP1998 提高组] 车站
先写一个表格,设上车人数为a,第二站上车的人数为b,可得下表:
站数 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 | 6 6 6 | 7 7 7 | 8 8 8 | 9 9 9 | 10 10 10 | … … … |
---|---|---|---|---|---|---|---|---|---|---|---|
总人数 | a a a | a a a | 2 a 2a 2a | 2 a + b 2a+b 2a+b | 3 a + 2 b 3a+2b 3a+2b | 4 a + 4 b 4a+4b 4a+4b | 6 a + 7 b 6a+7b 6a+7b | 9 a + 12 b 9a+12b 9a+12b | 14 a + 20 b 14a+20b 14a+20b | 22 a + 33 b 22a+33b 22a+33b | … … … |
上车人数 | a a a | b b b | a + b a+b a+b | a + 2 b a+2b a+2b | 2 a + 3 b 2a+3b 2a+3b | 3 a + 5 b 3a+5b 3a+5b | 5 a + 8 b 5a+8b 5a+8b | 8 a + 13 b 8a+13b 8a+13b | 13 a + 21 b 13a+21b 13a+21b | 21 a + 34 b 21a+34b 21a+34b | … … … |
下车人数 | 0 0 0 | b b b | b b b | a + b a+b a+b | a + 2 b a+2b a+2b | 2 a + 3 b 2a+3b 2a+3b | 3 a + 5 b 3a+5b 3a+5b | 5 a + 8 b 5a+8b 5a+8b | 8 a + 13 b 8a+13b 8a+13b | 13 a + 21 b 13a+21b 13a+21b | … … … |
我们用 u p i up _i upi 表示第 i i i 站上车的人数, d o w n i down _i downi 表示第 i i i 站下车的人数, a l l i all _i alli 表示第 i i i 站的总人数。观察一下上表,我们可以发现以下几点:
- u p i = d o w n i + 1 ; up_i=down_{i+1}; upi=downi+1;
- u p i = u p i − 1 + u p i − 2 ; up _i = up _{i-1}+up_{i-2}; upi=upi−1+upi−2;
-
a
l
l
i
=
a
l
l
i
−
1
+
u
p
i
−
4
+
u
p
i
−
3
=
a
l
l
i
−
1
+
u
p
i
−
2
;
all_i=all_{i-1}+up_{i-4}+up_{i-3}=all_{i-1}+up_{i-2};
alli=alli−1+upi−4+upi−3=alli−1+upi−2;
看第二点,我们可以很明显的看出,这是一个斐波那契数列,所以每站上车和下车的人数很快就能求出:
int i,up[31],down[31],n;
up[1]=a;
down[1]=0;
up[2]=down[2]=down[3]=b;//这里的b没有被赋值,所以初始值为0,可写可不写,原因是all[i]的值是一个含有未知数'b'的式子,无法求出,要在后面处理完后才能求出来,所以'b'只是一个象征性的变量,便于理解
for(i=3;i<=n;i++}
up[i]=up[i-1]+up[i-2],down[i+1]=up[i];
我们再来观察一下 a l l i all_i alli的 a a a、 b b b 个数的规律:
站数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
a a a 的个数 | 1 1 1 | 1 1 1 | 2 2 2 | 2 2 2 | 3 3 3 | 4 4 4 | 6 6 6 | 9 9 9 | 14 14 14 | 22 22 22 |
b b b 的个数 | 0 0 0 | 0 0 0 | 0 0 0 | 1 1 1 | 2 2 2 | 4 4 4 | 7 7 7 | 12 12 12 | 20 20 20 | 33 33 33 |
可以发现:
- 当 i ≥ 4 i≥4 i≥4 时,
-
- a i = a i − 1 + a i − 2 − 1 ; a_i=a_{i-1}+a_{i-2}-1; ai=ai−1+ai−2−1;
-
- b i = b i − 1 + b i − 2 + 1 ; b_i=b_{i-1}+b_{i-2}+1; bi=bi−1+bi−2+1;
非常简单可以推出:
int i,a[31],b[31];
n--;
b[0]=0;
a[1]=a[2]=b[2]=b[3]=b[4]=1;
a[3]=a[4]=2; //对a[4]的赋值是为了方便循环
for(i=4;i<=n;i++)
{
a[i]=a[i-1]+a[i-2]-1;
b[i]=b[i-1]+b[i-2]+1;
}
因为
a
l
l
i
all_i
alli 的值包含了
a
a
a 与
b
b
b,所以上面关于
u
p
i
up_i
upi、
d
o
w
n
i
down_i
downi 及
a
l
l
i
all_i
alli 的代码可不用。(那我写上面那些干嘛呢)
细心的同学可以发现,上面的伪代码内第二行有一句n--
,之所以要n–是因为
u
p
n
up_n
upn为0,
d
o
w
n
i
down_i
downi为
a
l
l
n
−
1
all_{n-1}
alln−1,所以要n--
。
接下来,我们已经知道了
a
l
l
i
all_i
alli 的值,得出了一个式子:
x
∗
a
i
+
y
∗
b
i
=
a
l
l
i
x*a_i+y*b_i=all_i
x∗ai+y∗bi=alli (
x
x
x、
y
y
y 为大于等于
5
5
5 的整数)
那么
y
y
y 的个数就为
(
a
l
l
i
−
x
∗
a
i
)
/
b
i
(all_i-x*a_i)/b_i
(alli−x∗ai)/bi.
完整代码:
#include<cstdio>
int a[31],b[31];
int i,j,a1,b1,m,x,n;
main()
{
scanf("%d %d %d %d",&a1,&n,&m,&x);
n--;
b[0]=b[1]=b[2]=0;
a[1]=a[2]=1;
a[3]=2;
for(i=4;i<=n;i++)
{
a[i]=a[i-1]+a[i-2]-1;
b[i]=b[i-1]+b[i-2]+1;
}
b1=(m-a[n]*a1)/b[n]; // b1:y的个数
printf("%d",a1*a[x]+b1*b[x]);
}