CF1288C Two Arrays
\(\large{题目链接}\)
\(\\\)
\(\Large\textbf{Solution: } \large{1.DP,详见\text{tlx blog xyx}}\) \(\Large{\text{tlx blog}}\) \(\\\)
\(\ \quad \quad \quad \quad \quad \quad\) \(\large{2. 由隔板法,方案数为C^{n-1}_{2m-n+1},然后线性求逆元即可。\\有种\text{O(n)}求阶乘逆元的方法,inv\left[ n+1\right] =\dfrac {1}{\left( n+1\right) !},所以可以倒序推出逆元,inv\left[ i+1\right] \times \left( i+1\right) =\dfrac {1}{i!}=inv\left[ i\right] 。}\)
\(\\\)
\(\Large\textbf{Code: }\)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 4010;
const int p = 1e9 + 7;
int n, m;
ll inv[N], s[N];
int read() {
int x = 0;
char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
return x;
}
inline ll quickpow(ll a, ll b) {
ll base = a, ans = 1;
for (; b ; b >>= 1, base = (base * base) % p) if (b & 1) ans = (ans * base) % p;
return ans;
}
int main() {
n = read(), m = read();
s[1] = 1;
for (int i = 2; i <= 3010; ++i) s[i] = (s[i - 1] * i) % p;
inv[3010] = quickpow(s[3010], p - 2);
for (int i = 3009; i >= 0; --i) inv[i] = inv[i + 1] * (i + 1) % p;
printf("%lld\n", s[n + 2 * m - 1] * inv[n - 1] % p * inv[m << 1] % p);
return 0;
}