NOIP 1998 车站(规律)

题目描述

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

 

输入

每个测试文件只包含一组测试数据,每组输入四个整数a、n、m和x。 

 

输出

对于每组输入数据,输出从x站开出时车上的人数。 

 

分析:

手动推一下规律可以得到下表:

上图中的b是设第二站上车b人,下车b人。

可以发现从第4项开始,净增加人数中的a的系数其实是Fibonacci数列,b的系数也是类似Fibonacci数列一直累加,用两个数组f1和f2分别记录两个系数,而当前总人数其实就是净增加人数的累加,求得总人数,就可以得到未知数b,然后再根据第x站a,b的系数,即可求得x站的人数。

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cctype>
#include<cstring>
#include<utility>
#include<cstdlib>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define Clear(x) memset(x,0,sizeof(x))
#define fup(i,a,b) for(int i=a;i<b;i++)
#define rfup(i,a,b) for(int i=a;i<=b;i++)
#define fdn(i,a,b) for(int i=a;i>b;i--)
#define rfdn(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
using namespace std;
const int maxn = 1e2+7;
const int inf = 0x3f3f3f3f;
const double pi=acos(-1.0);
const double eps = 1e-8;
int f1[maxn];
int f2[maxn];

int read()
{
    char ch=getchar();int ret=0,f=1;
    while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
    return f*ret;
}

int main()
{
    int a=read(),n=read(),m=read(),x=read();
    Clear(f1),Clear(f2);
    f1[1]=0,f1[2]=1;
    f2[1]=1,f2[2]=1;
    if(x==1||x==2)
    {
        printf("%d\n",a);
    }else if(x==3){
        printf("%d\n",2*a);
    }else{
        rfup(i,3,n-3)
        {
            f1[i]=f1[i-1]+f1[i-2];
            f2[i]=f2[i-1]+f2[i-2];
        }
        int sum1=2,sum2=0;
        rfup(i,1,n-4)
        {
            sum1+=f1[i];
            sum2+=f2[i];
        }
        int man=(m-a*sum1)/sum2;
        sum1=2,sum2=0;
        rfup(i,1,x-3)
        {
            sum1+=f1[i];
            sum2+=f2[i];
        }
        printf("%d\n",sum1*a+man*sum2);
    }
    return 0;
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值