zoukankan      html  css  js  c++  java
  • NOIP模拟题 斐波那契数列

    题目大意

    给定长度为$n$序列$A$,将它划分成尽可能少的若干部分,使得任意部分内两两之和均不为斐波那契数列中的某一项。

    题解

    不难发现$2 imes 10^9$之内的斐波那契数不超过$50$个

    先求出第$i$个数之前最后一个能和第$i$个数相加为斐波那契数的位置$last_i$。

    考虑每一部分$[l,r]$只需满足$max{last_i}<l(iin [l,r])$即可。

    那么设$F_i$表示以$i$为结尾最小化分数,那么转移到$i$的$j$显然是一段左右端点均单调不递减的区间,用单调队列维护即可。

    #include<bits/stdc++.h>
    #define debug(x) cerr<<#x<<" = "<<x
    #define sp <<"  "
    #define el <<endl
    #define LL long long
    #define M 100020
    #define MAXN 2000000000
    using namespace std;
    int read(){
    	int nm=0,fh=1; char cw=getchar();
    	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
    	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
    	return nm*fh;
    }
    map<int,int>MP; int n,m,p[M],F[M],last[M],G[M],q[M],hd,tl;
    int main(){
    	G[1]=1,G[2]=2,F[1]=1; n=read();
    	for(m=2;(LL)G[m-1]+(LL)G[m]<=MAXN;m++) G[m+1]=G[m]+G[m-1];
    	for(int i=1;i<=n;i++) p[i]=read();
    	MP[p[1]]=1,q[tl++]=0,q[tl++]=1;
    	for(int i=2,now=0;i<=n;i++){
    		last[i]=0;
    		for(int j=0;j<=m;j++){
    			if(!MP.count(G[j]-p[i])) continue;
    			int k=MP[G[j]-p[i]]; last[i]=max(last[i],k);
    		} now=max(now,last[i]);
    		while(q[hd]<now) hd++; F[i]=F[q[hd]]+1,MP[p[i]]=i;
    		while(F[q[tl-1]]>=F[i]&&hd<tl) tl--; q[tl++]=i;
    	}
    	printf("%d
    ",F[n]);
    	return 0;
    }
  • 相关阅读:
    scrapy框架(一)
    selenium爬取京东商品信息
    自动化测试工具selenium的使用
    xpath选择器的使用
    爬取网页数据实例
    爬虫实操
    爬虫之`beautifulsoup4`模块
    DNS学习笔记
    MongoDB集群部署
    MongoDB单机部署
  • 原文地址:https://www.cnblogs.com/OYJason/p/9900510.html
Copyright © 2011-2022 走看看