哈尔滨理工大学软件与微电子学院程序设计竞赛——K.Walk【逆元 & 组合数】

题目传送门


在这里插入图片描述


题解

  • 按理说应该用dp进行转移

  • 最短走法应该只往下和右

  • d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] dp[i][j]=dp[i−1][j]+dp[i][j−1] dp[i][j]=dp[i1][j]+dp[i][j1]

  • 但是这个 n , m n,m nm较大,不支持用二维数组和复杂度,并且还是多组输入

  • 那么直接用组合数进行计算

  • ( 1 , 1 ) (1,1) (1,1) ( n , m ) (n,m) (n,m)的路径往右和往下总共走 n + m − 2 n+m−2 n+m2

  • 其中往下走包括 n − 1 n-1 n1次,那么直接 C n + m − 2 n − 1 C_{n+m-2}^{n-1} Cn+m2n1

  • n + m − 2 n+m−2 n+m2步中选出 n − 1 n−1 n1步往下走,剩下的步数往右走

  • 所以直接预处理+逆元使用组合数


AC-Code

#include <bits/stdc++.h>
using namespace std;
 
const int maxn = (1e6+7)*2;
const int mod = 1e9 + 7;
 
typedef long long ll;
 
ll factorial[maxn] = { 1 }; // 阶乘
 
ll q_pow(ll a, ll b, ll mod) { // 快速幂
    ll res = 1LL;
    while (b) {
        if (b & 1)  res = (res * a) % mod;
        a = (a * a) % mod;
        b >>= 1;
    }
    return res % mod;
}
 
ll inv(ll x) {
    return q_pow(x, mod - 2, mod);
}
 
ll C(ll n, ll k) {
    return factorial[n] * inv(factorial[n - k] * factorial[k] % mod) % mod;
}
 
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    factorial[0] = 1;
    for (int i = 1; i <= maxn - 5; ++i)
        factorial[i] = (factorial[i - 1]) * i % mod;;
    int T;  cin >> T;
    while (T--) {
        ll N, M;    cin >> N >> M;
        cout << C(N + M - 2, N - 1) % mod << endl;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值