给定一个数 (n) 和一个数 (m),让构建两个数组 (a) 和 (b) 满足条件
- 数组中所有元素的取值在 ([1, n]) 之间
- (a) 和 (b) 数组长度是 (m)
- (a) 数组是单调不降的,(b) 数组是单调不增
- 任意的位置 (i),有 (a_i leq b_i)
Solution
首先很容易想到将 (b) 翻转后接在 (a) 的后面,那么问题就转化为用 ([1,n]) 填一个长度为 (2m) 的序列,使其单调不降的方案数
DP 解法
设 (f[i][j]) 表示填一个 (i) 长度的序列,最后一位为 (j) 的方案数,于是
[f[i][j]=f[i-1][j]+f[i-1][j-1]
]
暴力转移即可,时间复杂度 (O(nm))
组合
等价于求 (x_1+x_2+...+x_n=2m) 的解的方案数,于是考虑隔板法,答案为 (C_{2m+n-1}^{n-1})
时间复杂度 (O(n))
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9+7;
int qpow(int p,int q) {
return (q&1 ? p : 1) * (q?qpow(p*p%mod,q/2):1) % mod;
}
int inv(int p) {
return qpow(p,mod-2);
}
int frac(int p) {
int res = 1;
for(int i=2;i<=p;i++) res=res*i%mod;
return res;
}
int n,m;
signed main() {
cin>>n>>m;
cout<<frac(2*m+n-1)*inv(frac(n-1))%mod*inv(frac(2*m))%mod;
}