问题 J: 上下火车
时间限制: 1 Sec 内存限制: 125 MB
提交: 28 解决: 16
[提交][状态][讨论版][命题人:外部导入]
题目描述
火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上、下车,但上、下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人。从第3站起(包括第3站)上、下车的人数有一定规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第n-1站),都满足此规律。现给出的条件是:共有N个车站,始发站上车的人数为a,最后一站下车的人数是m(全部下车)。试问x站开出时车上的人数是多少?
输入
每个测试文件只包含一组测试数据,每组输入四个整数a、n、m和x。
输出
对于每组输入数据,输出从x站开出时车上的人数。
样例输入
5 7 32 4
样例输出
13
题意:列一下上下车人数会发现成一个斐波那契数列和的规律。已知斐波那契数列和求初项是困难的,所以采用二分的方法十分妥当。
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL maxn = 2000;
LL a,n,m,xx;
LL check(LL x)
{
LL s[maxn];
LL xia[maxn];
s[1]=a;
xia[1]=0;
s[2]=x;
xia[2]=x;
for(LL i=3;i<=n;i++){
s[i]=s[i-1]+s[i-2];
xia[i]=s[i-1];
}
s[n]=0;
LL sum=0;
for(LL i=1;i<n;i++){
sum+=s[i];
sum-=xia[i];
}
if(sum<=m){
return 1;
}else{
return 0;
}
}
LL f(LL x)
{
LL s[maxn];
LL xia[maxn];
s[1]=a;
xia[1]=0;
s[2]=x;
xia[2]=x;
for(LL i=3;i<=n;i++){
s[i]=s[i-1]+s[i-2];
xia[i]=s[i-1];
}
s[n]=0;
LL sum=0;
for(LL i=1;i<=xx;i++){
sum+=s[i];
sum-=xia[i];
}
if(xx==n) return 0;
return sum;
}
int main()
{
scanf("%lld %lld %lld %lld",&a,&n,&m,&xx);
LL l=0,r=m;
while(l<r){
LL mid = (l+r+1)>>1;
if(check(mid)){
l=mid;
}else{
r=mid-1;
}
}
printf("%lld\n",f(l));
return 0;
}