我们把一个数称为有趣的,当且仅当:
1、它的数字只包含 0,1,2,3,且这四个数字都出现过至少一次。
2、所有的 0 都出现在所有的 1 之前,而所有的 2 都出现在所有的 3 之前。
3、最高位数字不为 0。
因此,符合我们定义的最小的有趣的数是 2013。
除此以外,4 位的有趣的数还有两个:2031 和 2301。
请计算恰好有 n 位的有趣的数的个数。
由于答案可能非常大,只需要输出答案除以 109+7 的余数。
输入格式
输入只有一行,包括恰好一个正整数 n。
输出格式
输出只有一行,包括恰好 n 位的整数中有趣的数的个数除以 109+7 的余数。
数据范围
4≤n≤1000
思路:
列出限制条件:
根据最特殊的第二条,把所有数分为两类:01一类,23 一类
一共有n位数,设01一共有k位数,则23有n-k位数,由于第一个条件的限制,有2<=k<=n-2,所以枚举k,将算出来的个数相加,得到的就是总个数
来看当01有k位,23有n-k位时怎么算个数?
因为保证所有的0在1之前,2在3之前,所以0和1,2和3的相对位置不会改变,当所有01的位置填好后,剩下的就是23的位置
因为最高位不能为0,所以01的所有可能位置就是在除最高位的n-1个位置中选出来k个的选法:C(n-1,k)。然后在乘上所有不同的01组合,因为01一共有k位,0可能有m个1<=m<=k-1,一共有k-1种可能;最后在乘上所有不同的23组合,因为23一共有n-k位,2可能有m个1<=m<=n-k-1,一共有n-k-1种可能。
所以当01有k位,23有n-k位时,个数为C(n-1,k)×(k-1)×(n-k-1)
然后枚举k把所有的加起来就好了
const int N = 1e3+5, mod = 1e9+7;
int n,c[N][N];
void init()
{
for(int i=0;i<N;i++)
for(int j=0;j<=i;j++)
if(j==0) c[i][j]=1;
else c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
int main()
{
init();
cin>>n;
int ans=0;
for(int k=2;k<=n-2;k++)
ans=(ans+ (ll)c[n-1][k]*(k-1)%mod*(n-k-1))%mod;
cout<<ans<<endl;
return 0;
}