[1998NOIP提高组] 车站

题目描述
火车从始发站(称为第 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 站开出时车上的人数。
输入输出样例
输入
5 7 32 4
输出
13
说明/提示
对于全部的测试点,保证 1 ≤ a ≤ 20 1≤a≤20 1a20 1 ≤ x ≤ n ≤ 20 1≤x≤n≤20 1xn20 1 ≤ m ≤ 2 × 1 0 4 1≤m≤2×10^{4} 1m2×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=upi1+upi2;
  • 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=alli1+upi4+upi3=alli1+upi2;
    看第二点,我们可以很明显的看出,这是一个斐波那契数列,所以每站上车和下车的人数很快就能求出:
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 个数的规律:

站数12345678910
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 i4 时,
    • a i = a i − 1 + a i − 2 − 1 ; a_i=a_{i-1}+a_{i-2}-1; ai=ai1+ai21;
    • b i = b i − 1 + b i − 2 + 1 ; b_i=b_{i-1}+b_{i-2}+1; bi=bi1+bi2+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} alln1,所以要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 xai+ybi=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 (allixai)/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]); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值