车站问题 luogu(P1011)

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

a(≤20),n(≤20),m(≤2000),和x(≤20),

对于该题,我们并不知道从第二站开始上车的人数。所以不妨设为b。
则我们可以得到以下列表

在这里插入图片描述
乍一看,好像没有什么规律。但如果我们将其过程种上下车的人数也表现出来
就有下列表格
在这里插入图片描述
首先,注意“上a”与“上b”的表格,从第3站开始,系数呈现为斐波那契数列的特点;
其次,注意“下a"与”下b"的表格,从第5站开始,系数呈现为斐波那契数列的特点。

这样本题的关键点就被解决了。

a与b的系数为上车系数减去下车系数,得车上人数。

#include <iostream>
#define N  21
using namespace std;

int a1[N],b1[N],a2[N],b2[N],s[N],h[N];
//a1表示上a,a2表示下a, b1表示上b, b2表示下b, s存储a的系数,h存储b的系数
int main()
{
	int i;  int a,n,m,x,b,ans; cin>>a>>n>>m>>x;
	int sum=0,thm=0,sum1=0,thm1=0;
	a1[1]=1;a1[2]=0;b1[1]=0;b1[2]=1;
	for (i=3; i<=N; i++)
	{
		a1[i]=a1[i-1]+a1[i-2];         
		b1[i]=b1[i-1]+b1[i-2];
	}                                    //将a1与b1的元素确定

	
	a2[1]=0;a2[2]=0;a2[3]=0;a2[4]=1;
	b2[1]=0;b2[2]=1;b2[3]=1;b2[4]=1;
	for (i=5; i<=N; i++)
	{
		a2[i]=a2[i-1]+a2[i-2];     
		b2[i]=b2[i-1]+b2[i-2];
	}                                  //将a2与b2的元素确定
                      
                                       
	for (i=1; i<=n; i++)
	{
		s[i]=a1[i]-a2[i];
		h[i]=b1[i]-b2[i];
		sum+=s[i];
		thm+=h[i];
	}                                  //将s与h的元素确定,sum与thm,分别表示第n站a与b的系数
	

    b=(m-sum*a)/thm;                  //用n-1站的人数求出b
	
	if (x==n)                    
	{
		cout<<0<<endl;
		return 0;
	}                                 //终点站全部下车,车上人数为0
	if (x==1 || x==2) 
	{
		cout<<a<<endl;
		return 0;
	}
	if (x==3)
	{
		cout<<2*a<<endl;
		return 0;
	}
	else if (x>=4)
	{
	for (i=1; i<=x; i++)
	{
		sum1+=s[i];
		thm1+=h[i];
	}
	ans=sum1*a+thm1*b;
	cout<<ans<<endl;                        //计算并输出第x站的人数
	return 0;
   }
	
 } 

当然,该题的参考数最多只有20个,数目较少。也可以暴力解决——直接打表。

#include <iostream>
#define N  21
using namespace std;

int a1[N], b1[N];

int main()
{
	a1[N]={0,1,1,2,2,3,4,6,9,14,22,35,56,90,145,234,378,611,988,1598,2585};  //储存第i站a的系数 
	b1[N]={0,0,0,0,1,2,4,7,12,20,33,54,88,143,232,376,609,986,1596,2583,4180};  //储存第i站b的系数
    int a,n,m,x,b,ans; cin>>a>>n>>m>>x; 
	b=(m-a1[n-1]*a)/b1[n-1];                   //求b的值
	ans=a[x]*a + b[x]*b;
	cout<<ans<<endl;
	return 0;
}

十分简单粗暴,但对于数量较多时。。。自行领会。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值