1 条题解

  • 0
    @ 2024-12-24 1:27:21

    这道题是一道典型的动态规划题目,但是一看数据范围开不了这么大的数组。所以递推求方数这种方法失效了。

    我们可以在小数据内打表观察这个表格的性质。

    $$\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} $$

    这是通过递推的方式计算出的表格,看副对角线的每个数有啥关系。把表顺时针转 45°45° 你会惊奇的发现竟然是个杨辉三角。

    这样我们的答案就是杨辉三角里的某个数了,我们就可以通过其他方式得到,那么就是组合数!

    补充组合数的表示方法:(nk)=Cnk{n\choose k}=C_n^k 在算法竞赛中我们一般使用左侧表示方式表示组合数。

    我们的杨辉三角如下:

    $$\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} $$

    所以我们要求第 (i,j)(i,j) 位置的答案就是:

    (i+j2j1){i+j-2\choose j-1}

    我们只需要预处理阶乘和阶乘逆元就可以得到答案了,组合数公式为:

    (ab)=a!b!(ab)!{a\choose b}=\frac{a!}{b!(a-b)!}

    参考代码:

    #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
    上传者