| 試題編號: | 201312-4 |
| 試題名稱: | 有趣的數(shù) |
| 時間限制: | 1.0s |
| 內(nèi)存限制: | 256.0MB |
| 問題描述: | 問題描述 我們把一個數(shù)稱為有趣的,當(dāng)且僅當(dāng): 1. 它的數(shù)字只包含0, 1, 2, 3,且這四個數(shù)字都出現(xiàn)過至少一次?! ?. 所有的0都出現(xiàn)在所有的1之前,而所有的2都出現(xiàn)在所有的3之前?! ?. 最高位數(shù)字不為0?! ∫虼?,符合我們定義的最小的有趣的數(shù)是2013。除此以外,4位的有趣的數(shù)還有兩個:2031和2301。 請計算恰好有n位的有趣的數(shù)的個數(shù)。由于答案可能非常大,只需要輸出答案除以1000000007的余數(shù)。輸入格式 輸入只有一行,包括恰好一個正整數(shù)n (4 ≤ n ≤ 1000)。輸出格式 輸出只有一行,包括恰好n 位的整數(shù)中有趣的數(shù)的個數(shù)除以1000000007的余數(shù)。樣例輸入4樣例輸出3 |
原題鏈接:有趣的數(shù)。
問題描述:參見上文。
問題分析:這是一個計算問題,關(guān)鍵在于找到一個遞推式。只要找到一個遞推式,問題就解決了。有時候這類問題也用DP(動態(tài)規(guī)劃)來解決。
根據(jù)題意,有趣的數(shù)滿足以下約束條件如下:
1.只包含數(shù)字0、1、2和3
2.0、1、2和3各自至少出現(xiàn)一次
3.所有的0都出現(xiàn)在1之前
4.所有的2都出現(xiàn)在3之前
5.最高位數(shù)字不為0
數(shù)(字符串)可以分為以下六種情況(或稱為狀態(tài)):
1.只包含數(shù)字2,記為S1
2.只包含數(shù)字2和0(0開始的數(shù)0個,以此數(shù)為前綴的數(shù)均不是以0開始),記為S2
3.只包含數(shù)字2和3,記為S3
4.只包含數(shù)字2、0和1,并且滿足所有0在1之前,記為S4
5.只包含數(shù)字2、0和3,并且滿足所有2在3之前,記為S5
6.包含任意數(shù)字(包含0、1、2和3),滿足所有0在1之前,滿足所有2在3之前,記為S6
考慮遞推式:
1.對于S1,考慮其長度l,定義f(l,S1)為長度l的S1數(shù)的數(shù)量,則f(l,S1)=1。也就是說長度為l的只包含2的數(shù)只有1個。
2.對于S2,考慮其長度l,定義f(l,S2)為長度l的S2數(shù)的數(shù)量,當(dāng)l=1則那么f(l,S2)=0,即f(1,S2)=0,當(dāng)l>1則f(l,S2)=f(l-1,S2)*2+f(l-1,S1)。這是因為,長度為l的S2數(shù)可以是由長度為l-1的S2的數(shù)加上2或0構(gòu)成,例20為長度為2的S2數(shù),那么202和200為長度為3的S2數(shù);另外,長度為l的S2數(shù)可以是由長度為l-1的S1的數(shù)加上0構(gòu)成,例如22為長度為2的S1數(shù),那么220為長度為3的S2數(shù)。
3.對于S3,考慮其長度l,定義f(l,S3)為長度l的S3數(shù)的數(shù)量,當(dāng)l=1則那么f(l,S3)=0,即那么f(1,S3)=0,當(dāng)l>1則f(l,S3)=f(l-1,S3)*2+f(l-1,S1)。這是因為,長度為l的S3數(shù)可以是由長度為l-1的S3的數(shù)加上2或3構(gòu)成,例23為長度為2的S3數(shù),那么232和233為長度為3的S3數(shù);另外,長度為l的S3數(shù)可以是由長度為l-1的S1的數(shù)加上3構(gòu)成,例如22為長度為2的S1數(shù),那么223為長度為3的S3數(shù)。
4.對于S4,考慮其長度l,定義f(l,S4)為長度l的S4數(shù)的數(shù)量,當(dāng)l=1則那么f(l,S4)=0,即f(1,S4)=0,當(dāng)l>1則f(l,S4)=f(l-1,S4)*2+f(l-1,S2)+f(l-1,S3)。這是因為,長度為l的S4數(shù)可以是由長度為l-1的S4的數(shù)加上2或1構(gòu)成(滿足所有0在1之前,不可以加上0),例201為長度為3的S4數(shù),那么2012和2011為長度為4的S4數(shù);另外,長度為l的S4數(shù)可以是由長度為l-1的S2的數(shù)加上1構(gòu)成,例如20為長度為2的S2數(shù),那么201為長度為3的S4數(shù)。
同理,對于S5和S6,可以得到相應(yīng)的遞推公式。詳細(xì)參見以下的源程序。
有了遞推式,程序就可以根據(jù)遞推式,逐步進(jìn)行計算。
程序說明:(略)。
提交后得100分的C++語言程序如下:
/* CCF201312-4 有趣的數(shù) */#include <iostream>#include <cstring>using namespace std;const long long MOD = 1000000007;const int MAXN = 1000;const int MAXS = 5;long long status[MAXN+1][MAXS+1];int main(){ int n; cin >> n; memset(status, 0, sizeof(status)); // DP status[1][0] = 1; for(int i=2; i<=n; i++) { status[i][0] = 1; status[i][1] = (status[i - 1][1] * 2 + status[i - 1] [0]) % MOD; status[i][2] = (status[i - 1][2] + status[i - 1][0]) % MOD; status[i][3] = (status[i - 1][3] * 2 + status[i - 1][1] ) % MOD; status[i][4] = (status[i - 1][4] * 2 + status[i - 1][1] + status[i - 1][2]) % MOD; status[i][5] = (status[i - 1][5] * 2 + status[i - 1][3] + status[i - 1][4]) % MOD; } cout << status[n][5] << endl; return 0;}
新聞熱點
疑難解答