题意:
有一个1*n的矩阵,固定第一个数为1,其他填正整数 ,且相邻数的差不能超过1,求方案数%
的结果。
思路:
显然:
如果第
个格子的数是1,则第
个格子只有
或者
两种可能
而如果第
个格子的数不为1,则第
个格子一定有三种可能。
则当考虑
矩阵填法的方案数时,如果我们已经知道了
矩阵填法的方案数情况,假设:
:
矩阵填法的总方案数
:
矩阵填完以后第
个格子的数是
的总方案数。
则:
因为对于第
个格子填的数,如果第
个格子填数不为
,则一定有三种情况,而当为第
个格子为
时,只有两种情况,减去即可。
故此时核心便在于求出每一个
通过打表和面向 编程的方法(滑稽),我们能发现a[i]数列有一个名字,叫作Motzkin numbers,中文翻译为:默慈金数,其具有一个重要递推式,为:
Mot[0] = Mot[1] = 1;
for i : 2 to n
Mot[i] = ((2*i+1)*Mot[i-1] + 3*(i-1)*Mot[i-2])/(i+2)
故乘法逆元+递推可解。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int A = 1e6 + 10;
ll Mot[A],Ans[A],inv[A],n;
void init(){
inv[1] = 1;
for(ll i=2 ;i<=n+2 ;i++){
inv[i] = (mod - mod/i)*inv[mod%i]%mod;
}
}
int main(){
scanf("%I64d",&n);n--;
init();
Mot[0] = Mot[1] = 1;
Ans[0] = 1;Ans[1] = 2;
for(ll i=2 ;i<=n ;i++){
Mot[i] = ((2*i+1)%mod*Mot[i-1]%mod + 3*(i-1)%mod*Mot[i-2]%mod)*inv[i+2]%mod;
Ans[i] = (3*Ans[i-1]%mod - Mot[i-1])%mod;
}
if(Ans[n] < 0) Ans[n] += mod;
printf("%I64d\n",Ans[n]);
return 0;
}