2013年12月CCF计算机软件能力认证 第四题 有趣的数(有限状态机)

2021-03-04 10:37:56 浏览数 (1)

我们把一个数称为有趣的,当且仅当:

  1. 它的数字只包含 0,1,2,3且这四个数字都出现过至少一次。
  2. 所有的 0都出现在所有的 1 之前,而所有的 2 都出现在所有的 3 之前。
  3. 最高位数字不为 0。

因此,符合我们定义的最小的有趣的数是 2013。

除此以外,4 位的有趣的数还有两个:2031 和 2301。

请计算恰好有 n 位的有趣的数的个数。

由于答案可能非常大,只需要输出答案除以 10^9 7 的余数。

输入格式

输入只有一行,包括恰好一个正整数 n。

输出格式

输出只有一行,包括恰好 n 位的整数中有趣的数的个数除以 10^9 7 的余数。

数据范围

4≤n≤1000

输入样例:

代码语言:javascript复制
4

输出样例:

代码语言:javascript复制
3

思路:

考察有限状态机的转移:

我们不难发现只有六种情况:

0:只用了2

1: 只用了2、0

2:只用了2、3

3: 只用了2、0、3

4:只用了2 、0、1

5: 只用了2、0、1、3

可以用线性dp dp[n][i] 1<=i<=5 表示有n位 处于状态i的数目

状态转移我们随便举个例子分析一下,其他也是同样道理

比如dp[i][5]=(dp[i-1][3]%mod dp[i-1][4]%mod dp[i-1][5]*2%mod)%mod; 因为前面2013全有 所以下一位只能放 1 3;也可能是4状态转移过来 那就是填3;也可能是3状态填1转移过来

代码语言:javascript复制
#include<bits/stdc  .h>
using namespace std;
const int N=1010,mod=1e9 7;
int dp[N][6],n;
int main(){
    cin>>n;
    dp[1][0]=1;
    for(int i=2;i<=n;i  ){
        dp[i][0]=dp[i-1][0]%mod;
        dp[i][1]=(dp[i-1][0]%mod dp[i-1][1]*2%mod)%mod;
        dp[i][2]=(dp[i-1][0]%mod dp[i-1][2])%mod;
        dp[i][3]=(dp[i-1][1]%mod Xdp[i-1][2]%mod dp[i-1][3]*2%mod)%mod;
        dp[i][4]=(dp[i-1][1]%mod dp[i-1][4]*2%mod)%mod;
        dp[i][5]=(dp[i-1][3]%mod dp[i-1][4]%mod dp[i-1][5]*2%mod)%mod;
    }
    cout<<dp[n][5]%mod<<endl;
}

0 人点赞