動態規劃——有趣的數(ccf)
阿新 • • 發佈:2019-01-31
題目描述:
我們把一個數稱為有趣的,當且僅當:
1. 它的數字只包含0, 1, 2, 3,且這四個數字都出現過至少一次。
2. 所有的0都出現在所有的1之前,而所有的2都出現在所有的3之前。
3. 最高位數字不為0。
因此,符合我們定義的最小的有趣的數是2013。除此以外,4位的有趣的數還有兩個:2031和2301。
請計算恰好有n位的有趣的數的個數。由於答案可能非常大,只需要輸出答案除以1000000007的餘數。
解題思路:ccf的測試資料恐怖到極致,以至於我見了這道題根本沒有任何暴力的想法,我知道n位數與n-1位數絕對存在著某種關係~果然!
我們假設dp[i][j]表示填到第i位數時處於第j個狀態。
那麼共有六種合法狀態,括號表示重複出現的數字
0--01(2)3
1--(0)1(2)3
2--01(2)(3)
3--(0)(1)(2)3
4--(0)1(2)(3)
5--(0)(1)(2)(3)
那麼這個問題就很明顯了,任何n一種狀態,都是由滿足條件的幾個n-1狀態組成的
哦對了,注意每次都要取餘~
#include<stdio.h> /* dp[i][j]表示填到第i位數時處於第j個狀態。 共有六種合法狀態,括號表示重複出現的數字 0--01(2)3 1--(0)1(2)3 2--01(2)(3) 3--(0)(1)(2)3 4--(0)1(2)(3) 5--(0)(1)(2)(3) */ int main() { int i,n; __int64 dp[1010][10]; while(scanf("%d",&n)!=EOF) { for (i=1;i<=n;i++) { dp[i][0]=1; dp[i][1]=(dp[i-1][1]*2+dp[i-1][0])%1000000007; dp[i][2]=(dp[i-1][2]+dp[i-1][0])%1000000007; dp[i][3]=(dp[i-1][3]*2+dp[i-1][1])%1000000007; dp[i][4]=(dp[i-1][4]*2+dp[i-1][2]+dp[i-1][1])%1000000007; dp[i][5]=(dp[i-1][5]*2+dp[i-1][4]+dp[i-1][3])%1000000007; } printf("%I64d\n",dp[n][5]); } return 0; }