【問題描述】
化學不及格的Matrix67無奈選擇了文科。他必須硬着頭皮準備一次又一次的文科考試。
在這一學期一共有n次文科考試,考試科目有4種,分別爲政治、歷史、地理和綜合。每次考哪一科是不定的,因此在考試前Matrix67不知道應該去複習哪一科的功課。他希望能預測出下一次可能考的科目。於是,他收集到了以往的文科考試的資料。從以往的考試中,他發現了這樣幾個規律:
1.如果這次考的是政治,那麼下一次一定會考歷史;
2.如果這次考的是綜合,那麼下一次一定會考地理;
3.如果這次考的是歷史,那麼下一次要麼考政治,要麼考地理;
4.如果這次考的是地理,那麼下一次要麼考歷史,要麼考綜合。
Matrix67已經知道,本學期的第一次考試科目爲政治。他打算擬定一個可以應對所有可能情況的應考複習計劃。因此,他想知道,整個學期有多少種可能的考試科目安排滿足以上規律。
【輸入格式】
一個正整數n,代表本學期總的考試次數。輸入數據保證n<=10000。
【輸出格式】
一個正整數,表示符合規律的科目安排方案的總數。考慮到這個結果可能會很大,因此你只需要輸出它mod 7654321的值即可。
【輸入樣例】
5
【輸出樣例】
5
【樣例解釋】
當n=5時,有以下5種方案滿足要求:
- 政治–>歷史–>政治–>歷史–>政治
- 政治–>歷史–>政治–>歷史–>地理
- 政治–>歷史–>地理–>歷史–>政治
- 政治–>歷史–>地理–>歷史–>地理
- 政治–>歷史–>地理–>綜合–>地理
【數據範圍】
n<=10000
【來源】
Matrix67 根據經典問題改編
Vijos題庫 原題傳送矩陣
重慶一中題庫 原題傳送矩陣
【思路梳理】
不難想到模擬,運用遞推的思想,計算所有的方案數總和。那麼這樣做的時間複雜度只有O(n),目測應該能夠AC通過所有的數據。
思考一下高效算法,首先我們可以列出如下的表格和流程圖:
顯然第i次考試對應的是斐波那契數列的第i項,所以只需要遞歸地寫出求斐波那契數列第i項的函數即可,使用記憶化搜索,時間複雜度降低爲O(logn),能夠輕鬆通過所有數據。
【Cpp代碼】
#include<cstdio>
#include<iostream>
#define maxn 10005
using namespace std;
long long d[maxn];//使用int和long long都無妨
int n;
long long mod(long long x)
{
return x%7654321;//個人習慣,將取模寫作函數
}
long long f(int x)
{
if(x==1) return d[1]=1;
if(x==2) return d[2]=1;
if(d[x]) return d[x];//直接查表,記憶化搜索
return d[x]=mod(mod(f(x-2))+mod(f(x-1)));
}
int main()
{
scanf("%d",&n);//簡單分析一下就會發現是斐波那契數列,求的是該數列的第n項
cout<<f(n);
return 0;
}