火车从始发站(称为第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;
}
十分简单粗暴,但对于数量较多时。。。自行领会。