⭐⭐201312-4 有趣的数

一开始想用数组做,但是不知道要怎么循环,没想到竟然是动态规划!
status[i][j]表示长度为i状态为j的有趣的数个数
已知有趣的数一共有五种状态
整个字符串只有一个字符:由题意知这个字符只能是2
状态0:有2
整个字符串有两个字符:
状态1:有2、0
状态2:有2、3;且3在2后面
整个字符串有3个字符
状态3:有2、0、1;且1在0后面
状态4:有2、3、0;且3在2后面
整个字符串有4个字符:
状态5:有2、3、0、1;且3在2后面,1在0后面

下面可以知道
初始条件:

dp[1][0]=1;
dp[1][1]=0;
dp[1][2]=0;
dp[1][3]=0;
dp[1][4]=0;
dp[1][5]=0;

下面i从2到n迭代,最后dp[i][5]即为结果,迭代式子如下:

dp[i][0]=1;//显而易见
//只有2,长度为i-1的字符串在后面加上0
//有2,0,长度为i-1的字符串在后面加上2或则和0,所以要*2
dp[i][1]=dp[i-1][0]+2*dp[i-1][1];
//只有2,长度为i-1的字符串在后面加上3
//有2,3,长度为i-1的字符串,因为2只能在3前面,所以只能在i-1字符串后面加上3
dp[i][2]=dp[i-1][0]+dp[i-1][2];
//只有2、0,长度为i-1的字符串在后面加上1
//有2,0,1,长度为i-1的字符串,面加上2或者1
dp[i][3]=dp[i-1][1]+dp[i-1][3]*2;
//有2,0,长度为i-1的字符串在后面加上3
//有2,3,长度为i-1的字符串在后面加上0
//有2,0,3的字符串在后面加上3或者0
dp[i][4]=dp[i-1][1]+dp[i-1][2]+dp[i-1][4]*2;
//有2、0、1、3的字符串在后面加上1或者3
//和上面一样,类推
//和上面一样,类推
dp[i][5]=dp[i-1][5]*2+dp[i-1][3]+dp[i-1][4];

因为要模MOD=1000000007
所以每次计算dp都%MOD

同时注意dp数组开成long long

/* CCF201312-4 有趣的数 */
 
#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;
}

猜你喜欢

转载自blog.csdn.net/susuate/article/details/120218559