1. 程式人生 > >NOIP模擬 斐波那契(set+fib)

NOIP模擬 斐波那契(set+fib)

【題目描述】

斐波那契數列又稱兔子數列,可以通過以下方式產生:一開始只有一隻兔子,一個月之後這隻兔子每個月會繁殖出另一隻兔子。之後每隻兔子出生後都按照以上規則繁殖。我們把每個月的兔子的數量作為數列中的數就可以得到斐波那契數列。現在草原上有 n 只兔子排成一排,每隻兔子有一個繁殖能力 ai。小 F 想把這些兔子分組,要求一個組內的兔子必須是連續的一段。而且因為兔子們不太喜歡兔子數列,所以組內任意兩隻兔子的繁殖能力的和不能在兔子數列中出現。

現在小 F 想讓這些兔子的分組數量儘可能少,但是兔子很多,他算不過來,於是他找到了你,想讓你告訴他最少的分組數量是多少。

【輸入格式】

第一行一個整數 n,表示兔子的個數。

接下來一行 n 個數,依次表示 ai。

【輸出格式】

輸出一個數,表示最小的分組數量。

【樣例輸入】

5

1 5 2 6 7

【樣例輸出】

4

【備註】

對於 10% 的資料,n ≤ 20。

對於 30% 的資料,n ≤ 300。

對於 60% 的資料,n ≤ 1000。

對於 100 % 的資料,n ≤ 1e5, ai ≤ 1e9。

【題目分析】

好好的一到簽到題死於不會set。。。。60滾粗。。。。。

因為你選取的每一段都是連續的,所以完全可以邊加邊操作。因為兩個非法數之間最少劃分成兩段,所以順序不會影響。

接下來考慮判斷,每讀入一個數,判斷之前的數是否與之非法即可,因為2e9範圍內的fib數只有46個,所以複雜度可以接受,最終複雜度:O(46n)。

然後就是如何判斷與前面的數是否非法。。。。。藍瘦。。。。就有set這個東東,因為他有一個count功能可以查詢出現次數,如果前面出現了fib-a[i],那麼就非法,ans++。

【程式碼~】

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL MAXN=1e5+10;
const LL MAXM=1e14;

inline LL Read()
{
	LL i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

LL n;
LL a[MAXN],cnt;
LL fib[100];

void pre()
{
	fib[1]=fib[2]=1;
	for(LL i=3;i<=100&&fib[i-1]<=MAXM;++i)
	  fib[i]=fib[i-1]+fib[i-2],cnt++;
}

LL que[MAXN],tot,ans=1;
set<LL> check;
int main()
{
	pre();
	scanf("%d",&n);
	for(LL i=1;i<=n;++i)
	{
	    a[i]=Read();
	    bool flag=true;
	    for(int j=1;j<=cnt;++j)
	      if(check.count(fib[j]-a[i]))
	      {
	          flag=false;
	          break;
	      }
	    if(!flag)
		{
			check.clear();
			check.insert(a[i]);
	        ans++;
	    }
	    else
	      check.insert(a[i]);
	}
	printf("%lld\n",ans);
	return 0;
}