问题描述
我们把一个数称为有趣的,当且仅当:
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;
}