附上代码
一定要看下面的文字题解,单看代码有些晦涩
#include<stdio.h>
int sa[2002],sx[2002],da[2002],dx[2002];
int main()
{
int initnum,stanum,peo,loc;//开始有多少人,即a,总战术,最后一站下车的人数,计算第几站
scanf("%d%d%d%d",&initnum,&stanum,&peo,&loc);
//initnum是一开始上车的人数,stanum是车站的总数,peo是最后一站下车的人数,loc是题目所问的第几站
sa[0] = 1;
sa[1] = 0;
sa[2] = 1;
sa[3] = 1;
sx[0] = 0;
sx[1] = 1;
sx[2] = 1;
if(stanum >= 6)
for(int i = 4;i < stanum ;i++)
{
sa[i] = sa[i - 1] + sa[i - 2];
}
if(stanum >= 4)
for(int i = 3;i < stanum - 1;i++)
{
sx[i] =sx[i - 1] + sx[i - 2];
}
dx[1] = 1;
dx[2] = 1;
dx[3] = 1;
if(stanum >= 4)
{
for(int i = 4;i < stanum - 1;i++)
{
dx[i] = dx[i - 1] + dx[i - 2];
}
}
da[3] = 1;
da[4] = 1;
if(stanum > 5)
{
for(int i = 5;i < stanum - 1;i++)
{
da[i] = da[i - 1] + da[i - 2];
}
}
int suma = 0;
int sumx = 0;;
for(int i = 0;i <= stanum - 2;i++)
{
suma += (sa[i] - da[i]);
sumx += (sx[i] - dx[i]);
}
int x = (peo - suma * initnum) / sumx;
suma = 0;
sumx = 0;
for(int i = 0;i < loc;i++)
{
suma += (sa[i] - da[i]);
sumx += (sx[i] - dx[i]);
}
printf("%d",suma * initnum + sumx * x);
return 0;
}
先明确两个变量,一个是initnum,就是第一站的时候车上的人数,一个是x,就是在第二站上车的人数,
代码中我定义了四个数组,分别是
sa 斐波那契而数列中initnum前面的系数,
sx,最初上车人数x的系数,
da,每一站下车的人数中initnum前的系数,
dx,每一站下车人数x前的系数
通过亲自把数据列出来,我们可以发现,
第一站:上车initnum 人;车上有 initnum 人;
第二站:假设上车 x 人,则下车 x 人;车上仍然是initnum人;
第三站:上车人数等于前两站上车人数之和:initnum + x 人,下车人数等于上次上车人数 x 人;
第四站:上车人数 initnum + 2x,下车人数 initnum + x;
第五站:上车人数2initnum + 3x,下车人数 initnum +2x,
第六站:上车人数 3initnum + 5x,下车 2initnum +3x 人,
如果单看上车人数initnum前的系数,我们可以发现,他的系数是 1 0 1 1 2 3 5 8 13 21 …
如果单看上车人数前的系数,他们的系数是 0 1 1 2 3 5 8 13 21…
看下车人数initnum前的系数,他们是0 0 0 1 1 2 3 5 8 13 21 …
看下车人数x前的系数,他们是 0 1 1 1 2 3 5 8 13 21…
他们或许只有前几项不符合斐波那契额数列,但是几项过后,都是符合数列规律的。
所以我们可以选择一个不是很优雅的方法,就使将四个数列的前导列出来,然后根据车站的总数选择我们要计算的次数,将四个数列分别用数组存储起来,在后面解x的时候使用。
题上还告诉我们一个信息,就是最后一站下车的人数,我们可以通过将前n-1站上下车的斐波那契额数列的系数相加,让上车减下车的initnum的系数为suma,上车减下车的x系数为sumx,所以我们就有这个方程式
initnum * suma + x * sumx = 最后一站的下车人数
通过解这个方程就可以得到第二站上车的人数x,最后通过题目要求,求第几站,就按照上面一样的方法算出来就可以了,用数组注意不要越界啊
通过这个不美观的方法,就可以AC了
删除线格式
溜了溜了~~