1. 程式人生 > >CCF-CSP 練習題 有趣的數

CCF-CSP 練習題 有趣的數

題目

這裡寫圖片描述

分析

對於分治,動歸,遞迴不怎麼會的我沒什麼思路。。看了網上的思路後有了一點理解。利用動態規劃的方法來解決。設一個n位的整數,根據題目的要求,首位一定是2,所以我們就有了第一個狀態,即前幾位全為2,而0,1,3未被使用。我們可以在加上一個數0或3(1不符合規則,1必須在0的後面),所以第二種狀態為前幾位為2和0,1、3未出現。同理第三種狀態是出現2、3,0、1未出現。出現三個數,可以是2、0、1(第四種)或者2、0、3(第五種)。全部已經出現2、0、1、3(第六種情況)
一共有六種情況:
0 – 0 1 2 3
1 – 0 1 2 3
2 – 0 1 2 3
3 – 0 1 2 3
4 – 0 1 2

3
5 – 0 1 2 3

加粗的數字就是前k位出現過的數字。我們用二維陣列status[i][j] 表示當前數字的狀態(status[3][2]表示第3位的狀態為第2號狀態)。將陣列初始化為0,遍歷n位。0號情況只有一種(22222XXX ),status[i][0]=1。1號情況,0,2出現,他的前一位數(status[i-1][])狀態可能是0號情況(這一位只能為0)或者1號情況(可以是0或2)。所以status[i][1]=(status[i - 1][1] * 2 + status[i - 1][0]) % mod。其他情況道理一樣。

程式碼

#include<iostream>
using namespace std; int main() { long n; long long mod = 1000000007; long long status[10000][6] = { 0 }; cin >> n; for (int i = 1; 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][2] + status[i - 1][1]) % mod; status[i][5] = (status[i - 1][5] * 2 + status[i - 1][4] + status[i - 1][3]) % mod; } cout << status[n][5]; //system("pause"); return 0; }