ccf 有趣的数 DP

问题描述

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

1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次。

2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前。

3. 最高位数字不为0。

因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。

请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只需要输出答案除以1000000007的余数。

输入格式
输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000)。
输出格式
输出只有一行,包括恰好n 位的整数中有趣的数的个数除以1000000007的余数。
样例输入
4
样例输出
3


思路:我们通过规则可以发现,任意一个符合要求的数的首位只能是2。那么按照规则我们可以得出6种状态:

  1  只含有 2

2  只含有 2   0

3  只含有 2   3 

4  只含有 2   0   1

5  只含有 2   0   3 

6  含有全部四中数

             dp [ i ] [ j ] 表示一个 i 位数满足第 j 中状态。那么这一状态一定可以由第 i - 1 位数的每一状态得出。


#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
#define ll long long
const int mod=1000000007;
__int64 dp[1005][7]={0};
int main()
{
	int n,i,j,k,sum;
	dp[0][1]=1;
	for(i=1;i<=1000;i++)
	{
		dp[i][1]=dp[i-1][1];
		if(i>=2)
		{
			dp[i][2]+=dp[i-1][2]*2;
			dp[i][2]+=dp[i-1][1];
			dp[i][3]+=dp[i-1][3];
			dp[i][3]+=dp[i-1][1];
			dp[i][2]%=mod;
			dp[i][3]%=mod;
		}
		if(i>=3)
		{
			dp[i][4]+=dp[i-1][2];
			dp[i][4]+=dp[i-1][4]*2;
			dp[i][5]+=dp[i-1][2];
			dp[i][5]+=dp[i-1][3];
			dp[i][5]+=dp[i-1][5]*2;
			dp[i][4]%=mod;
			dp[i][5]%=mod;
		}
		if(i>=4)
		{
			dp[i][6]+=dp[i-1][4];
			dp[i][6]+=dp[i-1][5];
			dp[i][6]+=dp[i-1][6]*2;
			dp[i][6]%=mod;
		}
	}
	scanf("%d",&n);
	printf("%I64d\n",dp[n][6]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值