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;
} 

猜你喜欢

转载自www.cnblogs.com/Miraclys/p/12609297.html