1 条题解
-
0
这道题是一道典型的动态规划题目,但是一看数据范围开不了这么大的数组。所以递推求方数这种方法失效了。
我们可以在小数据内打表观察这个表格的性质。
$$\begin{array}{c|cccc} \text{$i/j$}&1&2&3&4&5\\ \hline 1&1&1&1&1&1\\ 2&1&2&3&4&5\\ 3&1&3&6&10&15\\ 4&1&4&10&20&35\\ 5&1&5&15&35&70\\ \end{array} $$这是通过递推的方式计算出的表格,看副对角线的每个数有啥关系。把表顺时针转 你会惊奇的发现竟然是个杨辉三角。
这样我们的答案就是杨辉三角里的某个数了,我们就可以通过其他方式得到,那么就是组合数!
补充组合数的表示方法: 在算法竞赛中我们一般使用左侧表示方式表示组合数。
我们的杨辉三角如下:
$$\begin{array}{c|cccc} \text{$i/j$}&1&2&3&4&5\\ \hline 1&{0\choose 0}&{1\choose 1}&{2\choose 2}&{3\choose 3}&{4\choose 4}\\ 2&{1\choose 0}&{2\choose 1}&{3\choose 2}&{4\choose 3}&{5\choose 4}\\ 3&{2\choose 0}&{3\choose 1}&{4\choose 2}&{5\choose 3}&{6\choose 4}\\ 4&{3\choose 0}&{4\choose 1}&{5\choose 2}&{6\choose 3}&{7\choose 4}\\ 5&{4\choose 0}&{5\choose 1}&{6\choose 2}&{7\choose 3}&{8\choose 4}\\ \end{array} $$所以我们要求第 位置的答案就是:
我们只需要预处理阶乘和阶乘逆元就可以得到答案了,组合数公式为:
参考代码:
#include <bits/stdc++.h> using u32 = unsigned; using i64 = long long; using u64 = unsigned long long; using u128 = unsigned __int128; constexpr int N = 400010, mod = 998244353; i64 fac[N], invfac[N]; i64 power(i64 a, i64 b) { i64 res = 1; while (b) { if (b & 1) res = res * a % mod; a = a * a % mod; b >>= 1; } return res; } i64 inv(i64 x) { return power(x, mod - 2); } void init(int n) { fac[0] = 1; invfac[0] = 1; for (int i = 1; i < n; i++) { fac[i] = fac[i - 1] * i % mod; invfac[i] = invfac[i - 1] * inv(i) % mod; } } i64 C(i64 a, i64 b) { if (a < b || b < 0) { return 0; } return (fac[a] * invfac[a - b] % mod * invfac[b]) % mod; } void solve() { int x, y; std::cin >> x >> y; std::cout << C(x + y - 2, y - 1) << "\n"; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); init(N); int t; std::cin >> t; while (t --) { solve(); } return 0; }
- 1
信息
- ID
- 153
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 39
- 已通过
- 6
- 上传者